Python深度学习(1):手写数字分类

《Python深度学习》手写数字分类有两个,在第二章用全连接网络实现,第五章用卷积神经网络实现。关于卷积神经网络的部分可以等到后面再看,先弄懂全连接网络。

1.数据集介绍

mnist是一个经典的手写测试集,包含6000万张训练图片和10000张测试图片,每张图片的大小为28*28

2.网络结构

全连接网络
本项目使用的网络结构并不复杂,只用了两个全连接层(fully connected layers,FC)。全连接层的作用是分类,本质上是多层感知机。
第一层(全连接层):输入为28*28,输出为512
第二层(全连接层):输入为512,输出为10

卷积神经网络
在这里插入图片描述

3.参数选择

很明显这是一个多分类、单标签问题(有10中类别,每个图片只能属于一种类别)

最后一层激活函数和损失函数选择

问题lossactivation
二分类二元交叉熵sigmoid
多分类,单标签分类交叉熵softmax
多分类,多标签二元交叉熵sigmoid
回归到任意直均方误差/
回归到0-1均方误差/二元交叉熵sigmoid
序列问题联结主义/

5.代码详解

函数介绍

其实每个函数的参数都有很多,每篇文章先介绍这次新用到的参数,循序渐进嘛。

Sequential
#Sequential顺序模型以组织网络层最简单的方式,可以自由用add线性堆叠网络层。
layers.Dense(units, activation,input_shape)
#全连接网络,分别表示输出的空间的维度,激活函数,输入空间的shape
model.compile(loss,optimizer,metrics)
#配置用于训练的模型,参数分别为损失函数,优化函数,评估指标,分类问题的评估指标一般选用accuracy
evaluate(x_test, y_test)
#评测模型在测试集上的效果,

全连接网络

from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

#调用mnist数据集
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
#将数据格式变为(图片数量,28*28),取值为0-1,因为每个点的像素值为8位,即范围为0-255,所以归一化的时候除以255
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

#将训练标签向量化,将每个标签标示为全零向量,只有标签索引对应的元素为1,即标签为1对应的标签向量为[1,0,0,0,0,0,0,0,0,0]
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

#搭建网络
network = models.Sequential()
#设置第一层全连接层
network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
#设置第一层全连接层,其返回一个由10个概率值组成的数组
network.add(layers.Dense(10, activation='softmax'))
network.compile(optimizer='rmsprop', loss = 'categorical_crossentropy', metrics=['accuracy'])

#训练网络
network.fit(train_images, train_labels, epochs=5, batch_size=128)

#测试模型在测试集上的性能
test_loss, test_acc = network.evaluate(test_images, test_labels)
print('test_acc:', test_acc)

运行结果
在这里插入图片描述

卷积神经网络

对于数据的处理与全连接网络都是一样的,只是换了一种网络结构。

from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32') / 255

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

#搭建网络
model = models.Sequential()
#第一层卷积层
model.add(layers.Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)))
#第二层最大池化层
model.add(layers.MaxPooling2D((2,2)))
#第三层卷积层
model.add(layers.Conv2D(64, (3,3), activation='relu'))
#第四层最大池化层
model.add(layers.MaxPooling2D((2,2)))
#第五层卷积层
model.add(layers.Conv2D(64, (3,3), activation='relu'))
#第六层Flatten层,将3D张量平铺为向量
model.add(layers.Flatten())
#第七层全连接层
model.add(layers.Dense(64, activation='relu'))
#第八层softmax层,进行分类
model.add(layers.Dense(10, activation='softmax'))

print(model.summary()) #输出网络结构

model.compile(optimizer='rmsprop', loss = 'categorical_crossentropy', metrics=['accuracy'])
model.fit(train_images, train_labels, epochs = 5, batch_size=64)

test_loss, test_acc = model.evaluate(test_images, test_labels)
print('test_acc = ', test_acc)

训练结果:
在这里插入图片描述

Pytorch代码详解

全连接网络

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets, transforms

#设置网络结构
class Net(nn.Module):
    def __init__(self, in_features, out_features):
        super(Net, self).__init__()
        self.dnn1 = nn.Linear(in_features, 512) #第一层全连接层
        self.dnn2 = nn.Linear(512, out_features) #第二层全连接层

    def forward(self, x):
        x = F.relu(self.dnn1(x)) #relu激活
        x = self.dnn2(x)
        return x

net = Net(28*28, 10)

#加载MNIST数据集
train_dataset =datasets.MNIST('./data', train=True, download=True,transform = transforms.ToTensor())
test_dataset = datasets.MNIST('./data', train=False, download=True,transform = transforms.ToTensor())

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset,  batch_size=128, shuffle=False)
# print(net)

# 开始训练
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.02)

for epoch in range(5):
    running_loss, running_acc = 0.0, 0.0
    for i, data in enumerate(train_loader):
        img, label = data
        img = img.reshape(-1,28*28)
        out = net(img)
        loss = criterion(out, label)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        running_loss += loss.item() * label.size(0)
        _, predicted = torch.max(out, 1)
        running_acc += (predicted==label).sum().item()
        print('Epoch [{}/5], Step [{}/{}], Loss: {:.6f}, Acc: {:.6f}'.format(
            epoch + 1, i + 1, len(train_loader), loss.item(), (predicted==label).sum().item()/128))
    #测试
    test_loss, test_acc = 0.0, 0.0
    for i, data in enumerate(test_loader):
        img, label = data
        img = img.reshape(-1, 28 * 28)
        out = net(img)
        loss = criterion(out, label)
        
        test_loss += loss.item() * label.size(0)
        _, predicted = torch.max(out, 1)
        test_acc += (predicted == label).sum().item()

    print("Train {} epoch, Loss: {:.6f}, Acc: {:.6f}, Test_Loss: {:.6f}, Test_Acc: {:.6f}".format(
        epoch + 1, running_loss / (len(train_dataset)), running_acc / (len(train_dataset)),
        test_loss / (len(test_dataset)), test_acc / (len(test_dataset))))

运行结果
在这里插入图片描述

卷积网络

只需要简单修改下网络结构就可

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets, transforms

# 设置网络结构
class Net(nn.Module):
    def __init__(self, in_features, out_features):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(in_features, 32, 3) #32,26,26
        self.max_pool1 = nn.MaxPool2d(kernel_size=2) # 32, 13, 13
        self.conv2 = nn.Conv2d(32, 64, 3) # 64, 11, 11
        self.max_pool2 = nn.MaxPool2d(kernel_size=2) # 64, 5, 5
        self.conv3 = nn.Conv2d(64, 64, 3) # 64,3,3
        self.dnn1 = nn.Linear(64*3*3, 64) #第一层全连接层 64
        self.dnn2 = nn.Linear(64, out_features) #第二层全连接层 10

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = self.max_pool1(x)
        x = F.relu(self.conv2(x))
        x = self.max_pool2(x)
        x = F.relu(self.conv3(x))
        x = x.view(128,-1)
        x = F.relu(self.dnn1(x)) #relu激活
        x = self.dnn2(x)
        return x

net = Net(1, 10)

print(net)
#加载MNIST数据集
train_dataset =datasets.MNIST('./data', train=True, download=True,transform = transforms.ToTensor())
test_dataset = datasets.MNIST('./data', train=False, download=True,transform = transforms.ToTensor())

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset,  batch_size=128, shuffle=False)


# 开始训练
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.02)

for epoch in range(5):
    running_loss, running_acc = 0.0, 0.0
    for i, data in enumerate(train_loader, 1):
        img, label = data
        out = net(img)
        loss = criterion(out, label)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        running_loss += loss.item() * label.size(0)
        _, predicted = torch.max(out, 1)
        running_acc += (predicted==label).sum().item()
        print('Epoch [{}/5], Step [{}/{}], Loss: {:.6f}, Acc: {:.6f}'.format(
            epoch + 1, i + 1, len(train_loader), loss.item(), (predicted==label).sum().item()/128))
    #测试
    test_loss, test_acc = 0.0, 0.0
    for i, data in enumerate(test_loader):
        img, label = data

        out = net(img)
        loss = criterion(out, label)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        test_loss += loss.item() * label.size(0)
        _, predicted = torch.max(out, 1)
        test_acc += (predicted == label).sum().item()

    print("Train {} epoch, Loss: {:.6f}, Acc: {:.6f}, Test_Loss: {:.6f}, Test_Acc: {:.6f}".format(
        epoch + 1, running_loss / (len(train_dataset)), running_acc / (len(train_dataset)),
        test_loss / (len(test_dataset)), test_acc / (len(test_dataset))))

运行结果
在这里插入图片描述

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值