Kaggle入门赛-Digit Recognizer(手写数字识别)

这篇具有很好参考价值的文章主要介绍了Kaggle入门赛-Digit Recognizer(手写数字识别)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


Kaggle入门赛-Digit Recognizer(手写数字识别)
Kaggle入门赛-手写数字识别所使用的数据集MNIST是计算机视觉上的“Hello world”数据集。这个经典的手写图像数据集一直作为基准分类算法的基础。随着新的机器学习技术的出现,MNIST仍然是研究人员和学习者的可靠资源。

本文所介绍的算法通过使用一个多层感知机来完成手写数字的识别。本文通过数据预处理与可视化、模型搭建与训练、模型结果预测等方面来介绍如何从kaggle下载数据集,并通过处理后的数据集训练模型,再到最后如何将模型预测的结果提交到kaggle。

Digit Recognizer(手写数字识别)比赛网址:https://www.kaggle.com/competitions/digit-recognizer/

1、数据处理与可视化

通过kaggle官网下载手写数据识别的数据集,如下图所示,下载的数据集有三个文件分别为train.csv,test.csv,sample_submission.csv,其中train.csv为训练集包含标签和手写数字图像,test.csv为测试集只包含手写数字图像不包含标签,sample_submission.csv为提交示例。更多详细的内容可查看官方的数据集介绍。

Kaggle入门赛-Digit Recognizer(手写数字识别)

首先导入所使用的相关包。

import pandas as pd
import numpy as np
import torch
import torch.utils.data as data
import matplotlib.pyplot as plt
import torch.nn.functional as F
from torch import nn
%matplotlib inline

导入训练集,并输出训练集前五条数据,可以看出训练集的第一列为标签值,后面783列为28×28图像的像素值的展开后的格式,训练集共有42000条数据。

df = pd.read_csv('train.csv')
print(df.head())
print(df['label'].count())
   label  pixel0  pixel1  pixel2  pixel3  pixel4  pixel5  pixel6  pixel7  \
0      1       0       0       0       0       0       0       0       0   
1      0       0       0       0       0       0       0       0       0   
2      1       0       0       0       0       0       0       0       0   
3      4       0       0       0       0       0       0       0       0   
4      0       0       0       0       0       0       0       0       0   

   pixel8  ...  pixel774  pixel775  pixel776  pixel777  pixel778  pixel779  \
0       0  ...         0         0         0         0         0         0   
1       0  ...         0         0         0         0         0         0   
2       0  ...         0         0         0         0         0         0   
3       0  ...         0         0         0         0         0         0   
4       0  ...         0         0         0         0         0         0   

   pixel780  pixel781  pixel782  pixel783  
0         0         0         0         0  
1         0         0         0         0  
2         0         0         0         0  
3         0         0         0         0  
4         0         0         0         0  

[5 rows x 785 columns]
42000

然后对训练集进行处理,将标签与图像分开。然后将标签与图像的值转为pytorch中的tensor,数据类型为浮点型。由于是分类任务,因此将标签转为one-hot编码。

首先从数据中将标签取出,然后将数据类型转为tensor。

#从数据中将标签取出,然后将数据类型转为tensor
labels=torch.from_numpy(np.array(df['label']))
labels
tensor([1, 0, 1,  ..., 7, 6, 9])

然后将标签值转为one-hot编码。torch.sparse实现稀疏张量,然后通过eye函数生成一个10维的单位矩阵,最后通过index_select(input, dim, index)函数生成one-hot编码,该函数在dim维度上将input中索引为index的值保存下来,从而得到labels的one-hot编码。

#转为one-hot
#生成单位矩阵
ones = torch.sparse.torch.eye(10)
print(ones)
#根据指定索引和维度保留单位矩阵中的一条数据即为one-hot编码
label_one_hot=ones.index_select(0,labels)
print(label_one_hot[0],labels[0])
tensor([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
tensor([0., 1., 0., 0., 0., 0., 0., 0., 0., 0.]) tensor(1)

将训练集中的图像部分转为tensor的浮点类型

df.pop('label')
#将训练集转为tensor
imgs=torch.from_numpy(np.array(df))
imgs = imgs.to(torch.float32)

定义构建数据集以及训练时所用的一些参数

#相关参数
#训练时的批量大小
train_batch_size=64
#训练轮次
num_epoches=20
#学习率
lr=0.01

通过DataLoader构造一个Pytorch数据迭代器,获得指定batch_size的数据迭代器,便于在训练时取出指定batch_size的训练数据。

#构造一个Pytorch数据迭代器
def load_array(data_arrays,batch_size,is_train=True):
    #加星号说明为元组
    #TensorDataset 可以用来对 tensor 进行打包
    dataset=data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset,batch_size,shuffle=is_train)
train_data=load_array((imgs,label_one_hot), batch_size=train_batch_size)

数据可视化,从生成的数据中随机抽取进行可视化并展示标签值。

#enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
exaples=enumerate(train_data)
#next() 返回迭代器的下一个项目
batch_idx,(example_img,example_label) = next(exaples)
fig=plt.figure()
for i in range(6):
    plt.subplot(2,3,i+1)
    plt.tight_layout()
    plt.imshow(example_img[i].reshape(28,28),cmap='gray',interpolation='none')
    _,prd=example_label[i].max(0)
    plt.title('Ground Truth:{}'.format(prd))
    plt.xticks([])
    plt.yticks([])


Kaggle入门赛-Digit Recognizer(手写数字识别)

2、模型搭建与训练

将数据处理完成之后,接下来就是定义模型,并使用处理好的数据对模型进行训练的阶段了,在此使用了一个多层感知机网络进行手写数字识别。

首先搭建用于模型训练的网络模型。在这里使用了一个三层的多层感知机,在每个线性层之后都使用了批量归一化以防止梯度消失的问题,激活函数选用了ReLU激活函数也更好的避免了梯度消失的问题。

class Net(nn.Module):
    def __init__(self,in_dim,n_hidden_1,n_hidden_2,out_dim):
        super(Net,self).__init__()
        self.layer1=nn.Sequential(nn.Linear(in_dim,n_hidden_1),nn.BatchNorm1d(n_hidden_1))
        self.layer2=nn.Sequential(nn.Linear(n_hidden_1,n_hidden_2),nn.BatchNorm1d(n_hidden_2))
        self.layer3=nn.Sequential(nn.Linear(n_hidden_2,out_dim))
    def forward(self,x):
        x=F.relu(self.layer1(x))
        x=F.relu(self.layer2(x))
        x=self.layer3(x)
        #x=F.softmax(self.layer3(x))
        return x

下面就可以实例化我们定义的模型,手写数字图片共有784个像素值,因此输入为784维,两个隐藏层的大小分别问300和100,最后输出层维度为10将数字分为0-9十类。为加快训练速度并在有GPU的条件下,可将模型放到GPU上训练。

#检测是否有可用的设备
device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

#实例化网络
model=Net(784,300,100,10)
model.to(device)
Net(
  (layer1): Sequential(
    (0): Linear(in_features=784, out_features=300, bias=True)
    (1): BatchNorm1d(300, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  )
  (layer2): Sequential(
    (0): Linear(in_features=300, out_features=100, bias=True)
    (1): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  )
  (layer3): Sequential(
    (0): Linear(in_features=100, out_features=10, bias=True)
  )
)

定义损失函是和优化器,损失函数采用交叉熵损失函数,优化器使用Adam,该优化算法可以动态改变学习率。

#损失函数和优化器
criterion=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=lr,betas=(0.9,0.99))

然后就可以训练训练我们的模型了

#训练网络
losses=[]
acces=[]

for epoch in range(num_epoches):
    train_loss=0
    train_acc=0
    model.train()
    for img,label in train_data:
        #将图片和标签放入GPU设备
        img=img.to(device)
        label=label.to(device)
        #计算结果
        out=model(img)
        #计算损失
        loss=criterion(out,label)
        #将梯度清零
        optimizer.zero_grad()
        #反向传播
        loss.backward()
        #更新网络参数
        optimizer.step()
        
        #记录训练损失
        train_loss+=loss.item()
        #记录训练准确度
        _,pred=out.max(1)
        l,pred1=label.max(1)
        num_correct=(pred==pred1).sum().item()
        acc=num_correct/img.shape[0]
        train_acc+=acc
    losses.append(train_loss/len(train_data))
    acces.append(train_acc/len(train_data))
    print('epoch:{},Train Loss:{:.4f},Train Acc:{:.4f}'.format(epoch,train_loss/len(train_data),train_acc/len(train_data)))
epoch:0,Train Loss:0.2226,Train Acc:0.9309
epoch:1,Train Loss:0.1126,Train Acc:0.9655
epoch:2,Train Loss:0.0823,Train Acc:0.9739
epoch:3,Train Loss:0.0623,Train Acc:0.9799
epoch:4,Train Loss:0.0526,Train Acc:0.9829
epoch:5,Train Loss:0.0450,Train Acc:0.9854
epoch:6,Train Loss:0.0378,Train Acc:0.9879
epoch:7,Train Loss:0.0351,Train Acc:0.9889
epoch:8,Train Loss:0.0313,Train Acc:0.9897
epoch:9,Train Loss:0.0254,Train Acc:0.9911
epoch:10,Train Loss:0.0259,Train Acc:0.9912
epoch:11,Train Loss:0.0255,Train Acc:0.9920
epoch:12,Train Loss:0.0242,Train Acc:0.9924
epoch:13,Train Loss:0.0217,Train Acc:0.9935
epoch:14,Train Loss:0.0207,Train Acc:0.9933
epoch:15,Train Loss:0.0218,Train Acc:0.9930
epoch:16,Train Loss:0.0197,Train Acc:0.9942
epoch:17,Train Loss:0.0192,Train Acc:0.9942
epoch:18,Train Loss:0.0180,Train Acc:0.9941
epoch:19,Train Loss:0.0171,Train Acc:0.9943

最终的准确率达到了99%多,看起来结果很不错,但这只是在训练集上的结果,在测试集上就不可能达到这个结果了。

将训练准确度和训练损失数值进行可视化,直观观察训练的结果。

plt.title('train loss and acc')
plt.plot(np.arange(len(losses)),losses)
plt.plot(np.arange(len(losses)), losses, color='red',label='Train Loss')
plt.plot(np.arange(len(losses)),acces, color='green', label='Train Acc')
plt.legend()
<matplotlib.legend.Legend at 0x2ded4f62fc8>


Kaggle入门赛-Digit Recognizer(手写数字识别)

3、模型预测结果

模型训练完成之后,就可以使用训练集中的数据生成最终的结果,然后将结果上传到kaggle就可以看到我们的模型在测试集上到底可以得到多少分数了。

首先我们先处理一下测试集,将数据转为tensor的float32类型。

#读取测试集
df_test = pd.read_csv('test.csv')
test_imgs=torch.from_numpy(np.array(df_test))
test_imgs = test_imgs.to(torch.float32)
test_imgs
tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        ...,
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]])

将测试集放到GPU上,然后传入训练好的模型中得到预测的结果,并转为DataFrame类型便于生成上传到kaggle的结果集。

#test_img=torch.unsqueeze(test_imgs[0],0)
test_imgs=test_imgs.to(device)
_,pre=model(test_imgs).max(1)
res={}
pre = pre.cpu().numpy()
pre_size=pre.shape[0]
num = [i for i in range(1,pre_size+1)]
res_df=pd.DataFrame({
    'ImageId':num,
    'Label':pre
})

查看结果的前五行。

res_df.head()
ImageId Label
0 1 2
1 2 0
2 3 9
3 4 9
4 5 3

将结果输出到csv文件中。

res_df.to_csv('res.csv',index=False)

最后,将结果上传到kaggle中,就可以查看到模型在测试集上的准确率。

Kaggle入门赛-Digit Recognizer(手写数字识别)

最终使用多层感知机可以达到0.97846的结果,后面会在使用卷积神经网络测试一下可以达到多少准确率,后面在更新。。。

4、代码整合

数据处理、模型搭建、模型训练部分,去掉了数据可视化和训练结果可视化部分。

import pandas as pd
import numpy as np
import torch
import torch.utils.data as data
import matplotlib.pyplot as plt
import torch.nn.functional as F
from torch import nn
%matplotlib inline

#读取数据
df = pd.read_csv('train.csv')
#从数据中将标签取出,然后将数据类型转为tensor
labels=torch.from_numpy(np.array(df['label']))
#转为one-hot
ones = torch.sparse.torch.eye(10)
label_one_hot=ones.index_select(0,labels)
#将标签给从数据集中删除,得到训练集的输入数据
df.pop('label')
#将训练集转为tensor
imgs=torch.from_numpy(np.array(df))
imgs = imgs.to(torch.float32)

#相关参数
train_batch_size=64
num_epoches=20
lr=0.01

#构造一个Pytorch数据迭代器
def load_array(data_arrays,batch_size,is_train=True):
    #加星号说明为元组
    #TensorDataset 可以用来对 tensor 进行打包
    dataset=data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset,batch_size,shuffle=is_train)
train_data=load_array((imgs,label_one_hot), batch_size=train_batch_size)

#模型搭建
class Net(nn.Module):
    def __init__(self,in_dim,n_hidden_1,n_hidden_2,out_dim):
        super(Net,self).__init__()
        self.layer1=nn.Sequential(nn.Linear(in_dim,n_hidden_1),nn.BatchNorm1d(n_hidden_1))
        self.layer2=nn.Sequential(nn.Linear(n_hidden_1,n_hidden_2),nn.BatchNorm1d(n_hidden_2))
        self.layer3=nn.Sequential(nn.Linear(n_hidden_2,out_dim))
    def forward(self,x):
        x=F.relu(self.layer1(x))
        x=F.relu(self.layer2(x))
        x=self.layer3(x)
        #x=F.softmax(self.layer3(x))
        return x
    
#检测是否有可用的设备
device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

#实例化网络
model=Net(784,300,100,10)
model.to(device)

#损失函数和优化器
criterion=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=lr,betas=(0.9,0.99))

#训练网络
losses=[]
acces=[]

for epoch in range(num_epoches):
    train_loss=0
    train_acc=0
    model.train()
    #动态修改学习率
   # if epoch%5==0:
    #    optimizer.param_groups[0]['lr']*=0.1
    for img,label in train_data:
        img=img.to(device)
        label=label.to(device)
        
        out=model(img)
        loss=criterion(out,label)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        train_loss+=loss.item()
        
        _,pred=out.max(1)
        l,pred1=label.max(1)
        num_correct=(pred==pred1).sum().item()
        acc=num_correct/img.shape[0]
        train_acc+=acc
    losses.append(train_loss/len(train_data))
    acces.append(train_acc/len(train_data))
    print('epoch:{},Train Loss:{:.4f},Train Acc:{:.4f}'.format(epoch,train_loss/len(train_data),train_acc/len(train_data)))
epoch:0,Train Loss:0.2245,Train Acc:0.9318
epoch:1,Train Loss:0.1169,Train Acc:0.9640
epoch:2,Train Loss:0.0832,Train Acc:0.9728
epoch:3,Train Loss:0.0623,Train Acc:0.9805
epoch:4,Train Loss:0.0499,Train Acc:0.9840
epoch:5,Train Loss:0.0438,Train Acc:0.9859
epoch:6,Train Loss:0.0395,Train Acc:0.9873
epoch:7,Train Loss:0.0314,Train Acc:0.9895
epoch:8,Train Loss:0.0307,Train Acc:0.9899
epoch:9,Train Loss:0.0274,Train Acc:0.9910
epoch:10,Train Loss:0.0259,Train Acc:0.9915
epoch:11,Train Loss:0.0237,Train Acc:0.9919
epoch:12,Train Loss:0.0243,Train Acc:0.9922
epoch:13,Train Loss:0.0226,Train Acc:0.9927
epoch:14,Train Loss:0.0199,Train Acc:0.9937
epoch:15,Train Loss:0.0192,Train Acc:0.9937
epoch:16,Train Loss:0.0194,Train Acc:0.9934
epoch:17,Train Loss:0.0177,Train Acc:0.9944
epoch:18,Train Loss:0.0179,Train Acc:0.9947
epoch:19,Train Loss:0.0177,Train Acc:0.9944

结果预测以及导出为csv文件部分文章来源地址https://www.toymoban.com/news/detail-489282.html

#读取测试集
df_test = pd.read_csv('test.csv')
test_imgs=torch.from_numpy(np.array(df_test))
test_imgs = test_imgs.to(torch.float32)

#测试集预测部分
#传入GPU
test_imgs=test_imgs.to(device)
#计算结果
_,pre=model(test_imgs).max(1)
#将结果转为提交kaggle的格式
res={}
pre = pre.cpu().numpy()
pre_size=pre.shape[0]
num = [i for i in range(1,pre_size+1)]
res_df=pd.DataFrame({
    'ImageId':num,
    'Label':pre
})

#d导出为CSV文件
res_df.to_csv('res.csv',index=False)

到了这里,关于Kaggle入门赛-Digit Recognizer(手写数字识别)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 卷积神经网络(CNN)入门:使用Python实现手写数字识别

    在上一篇文章中,我们介绍了如何使用Python实现一个简单的前馈神经网络。本文将重点介绍卷积神经网络(CNN),这是一种在计算机视觉任务中表现优异的深度学习模型。我们将从卷积神经网络的基本原理开始,介绍卷积层、池化层和全连接层等概念,然后使用Python和Keras库

    2023年04月15日
    浏览(53)
  • 吴恩达471机器学习入门课程2第2周——手写数字识别(0到9)

    使用神经网络来识别手写数字0-9。 本周,引入了一种新的激活函数,即修正线性单元(ReLU)。 a = m a x ( 0 , z )  ReLU函数 a = max(0, z) quadquadtext{ ReLU函数} a = ma x ( 0 , z )  ReLU 函数 讲座中的例子展示了ReLU的应用。在这个例子中,上下文感知能力不是二进制的,而是具有连续的

    2024年02月09日
    浏览(36)
  • 入门深度学习——基于全连接神经网络的手写数字识别案例(python代码实现)

    1.1 问题导入 如图所示,数字五的图片作为输入,layer01层为输入层,layer02层为隐藏层,找出每列最大值对应索引为输出层。根据下图给出的网络结构搭建本案例用到的全连接神经网络 1.2 手写字数据集MINST 如图所示,MNIST数据集是机器学习领域中非常经典的一个数据集,由6

    2024年02月03日
    浏览(46)
  • 手写数字识别(识别纸上手写的数字)

    说明 使用pytorch框架,实现对MNIST手写数字数据集的训练和识别。重点是,自己手写数字,手机拍照后传入电脑,使用你自己训练的权重和偏置能够识别。数据预处理过程的代码是重点。 分析 要识别自己用手在纸上写的数字,从特征上来看,手写数字相比于普通的电脑上的数

    2024年02月03日
    浏览(40)
  • 【10个适合新手的人工智能项目 - 02】手写数字识别:使用Python和机器学习算法,编写一个手写数字识别程序,能够识别手写数字图像并将其转换为数字。

    为了编写一个手写数字识别程序,我们需要使用Python编程语言和一些机器学习算法。在这个项目中,我们将使用深度学习神经网络模型,它被广泛应用于图像识别任务。 以下是手写数字识别程序的基本步骤: 首先,我们需要一个数据集,用于训练和测试我们的模型。一个常

    2024年02月03日
    浏览(57)
  • [Pytorch]手写数字识别——真·手写!

    Github网址:https://github.com/diaoquesang/pytorchTutorials/tree/main 本教程创建于2023/7/31,几乎所有代码都有对应的注释,帮助初学者理解dataset、dataloader、transform的封装,初步体验调参的过程,初步掌握opencv、pandas、os等库的使用,😋纯手撸手写数字识别项目(为减少代码量简化了部分

    2024年02月14日
    浏览(79)
  • 机器学习——手写数字识别

    这篇文章能够帮助你从数据到模型的整个过程实现 不过至于安装第三方库等基础问题,本文不涉及,因为确实不难,搜一搜一大把 本此实验运行环境为jupyter,当然通过pycharm也是可行的 手写数字共5000组数组 其中一共有0-9,10组数据,每一组中有500张对应的手写数字的图片

    2024年02月10日
    浏览(35)
  • AI手写数字识别(二)

    上文主要介绍了人工智能模型的集成过程。人工智能模型的正确集成,是我们案例中人工智能应用开发的核心步骤。但要让一个人工智能应用顺利地被使用,除了集成模型之外的一些工作也是必不可少的,比如处理输入的数据,进行界面交互等。 应用的主体逻辑都在 MNIST.A

    2024年01月24日
    浏览(42)
  • 神经网络基础-手写数字识别

    基本原理 图像本质上被认为是一个矩阵,每个像素点都是一个对应的像素值,相当于在多维数据上进行相关的归类或者其他操作。 线性函数 线性函数的一个从输入到输出的映射,用于给目标一个每个类别对应的得分。 图像 ( 32 ∗ 32 ∗ 3 ) → f ( x , W ) Y 图像(32*32*3) stackrel{

    2024年02月02日
    浏览(39)
  • 手写数字识别及python实现

    目录 1、总体流程 2、代码实现 下载数据集 确定激活函数、损失函数、计算梯度函数等 神经网络的搭建 模型的训练与验证  测试模型的泛化能力 step1:下载数据集、读取数据 step2:搭建神经网络(确定输出层、隐藏层(层数)、输出层的结构) step3:初始化偏置和权重 ste

    2024年02月07日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包