人工智能导论实验报告-神经网络算法

一、实验目的

1、 掌握PyTorch基于MNIST数据的CNN网络。

2、 掌握神经网络算法,重点是卷积神经网络算法。

二、实验原理

神经网络是当前深度学习领域普遍所应用的。它是一种高度并行的信息处理系统,具有很强的自适应学习能力,不依赖于研究对象的数学模型,对被控对象的系统参数变化及外界干扰有很好的鲁棒性,能处理复杂的多输入、多输出非线性系统,神经网络要解决的基本问题是分类问题。

​ 卷积神经网络(CNN)主要是用于图像识别领域,它指的是一类网络,而不是某一种,其包含很多不同种结构的网络。不同的网络结构通常表现会不一样。

​ LeNet-5 这个网络虽然很小,但是它包含了深度学习的基本模块:卷积层,池化层,全连接层。是其他深度学习模型的基础。LeNet-5共有7层,不包含输入,每层都包含可训练参数;每个层有多个Feature Map,每个FeatureMap通过一种卷积滤波器提取输入的一种特征,然后每个FeatureMap有多个神经元。

​ MNIST是一个手写体数字的图片数据集,该数据集来由美国国家标准与技术研究所(National Institute of Standards and Technology (NIST))发起整理,一共统计了来自250个不同的人手写数字图片,其中50%是高中生,50%来自人口普查局的工作人员。该数据集的收集目的是希望通过算法,实现对手写数字的识别。MNIST 数据集可在MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges 获取, 它包含了四个部分:

​ Training set images: train-images-idx3-ubyte.gz (9.9MB, 解压后47MB, 包含60,000个样本)

​ Training set labels: train-labels-idx1-ubyte.gz (29KB, 解压后60KB, 包含60,000个标签)

Test set images: t10k-images-idx3-ubyte.gz (1.6MB, 解压后 7.8 MB, 包含10,000个样本)。

Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含10,000个标签)。

三、实验步骤及内容

1、实数据集准备

在实验开始之前,需要准备一个手写字体数据集。这个数据集应该包含各种不同风格的手写字体,例如正楷、草书等。数据集应该包括每个字体的样本图片,以及对应的标签(即字体的真实值)。

2、数据预处理

在数据预处理阶段,需要对每个样本图片进行预处理。这包括图像去噪、二值化、尺寸归一化等操作。这些操作可以消除字体大小、方向、笔划粗细等因素对手写字体识别的影响。

3、特征提取

特征提取是手写字体识别的关键步骤。在这个阶段,需要使用一种或多种特征提取方法,如卷积神经网络(CNN)特征、结构化局部二值模式(SLBP)特征等,从预处理后的图像中提取出有意义的特征。这些特征可以用于后续的分类器训练。

4、模型训练

在模型训练阶段,需要使用提取的特征训练分类器。常用的分类器包括支持向量机(SVM)、神经网络等。在这个阶段,需要调整模型的参数,以优化模型的性能。

5、模型评估

在模型评估阶段,需要使用测试集对模型进行评估。常用的评估指标包括准确率、召回率等。通过这些指标,可以了解模型的性能如何,以及模型是否能够正确识别手写字体。

6、模型优化

如果模型的性能不满意,需要进行模型优化。这可能包括调整模型的参数、改进特征提取方法等。通过优化模型,可以提高模型的性能,提高手写字体识别的准确率。

四、实验代码

# 导入所需要的包

import torchvision

from torchvision.datasets import MNIST

from torch.utils.data import DataLoader

from torchvision import transforms

import torch

import numpy as np

import matplotlib.pyplot as plt

import time

import torch

from torch import nn, optim



# 定义一个转换以张量的形式读取数据

transform = transforms.Compose([transforms.ToTensor()])



train_data = MNIST(root='sdata', train=True, download=True, transform=transform)



test_data = MNIST(root='sdata', train=False, download=True, transform=transform)



# 设置数据批量大小为100使用DalaLoader加载器分别得到可迭代对象train_iter,test_iter

batch_size = 100

train_iter = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True)

test_iter = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=False)



# 展示训练集中的图片image以及标签label

batch = next(iter(train_iter))

images, labels = batch

print('types', type(images), type(labels))

print('shapes', images.shape, labels.shape)

# 图片都是1*28*28的大小C,H,W

# ToTensor()将shape为(H,W,C)的nump,ndarray或img转化为shape为(C,H,W)的tensor,其将每一个数值归一化到[0,1]



# 使用torchvision中的方法,同时展示多张图片

grid = torchvision.utils.make_grid(images, nrow=10)

print(grid.shape)



# 使用matplotlib展示多个图片以及图像所对应的labels

plt.figure(figsize=(8, 8))

plt.imshow(np.transpose(grid, (1, 2, 0)))

print('labels', labels)





# 定义Alexnet网络结构

class LeNet(nn.Module):

    def __init__(self):

        super(LeNet, self).__init__()

        self.conv = nn.Sequential(

            nn.Conv2d(1, 6, 5),

            nn.Sigmoid(),

            nn.MaxPool2d(2, 2),

            nn.Conv2d(6, 16, 5),

            nn.Sigmoid(),

            nn.MaxPool2d(2, 2)

        )

        self.fc = nn.Sequential(

            nn.Linear(16 * 4 * 4, 120),

            nn.Sigmoid(),

            nn.Linear(120, 84),

            nn.Sigmoid(),

            nn.Linear(84, 10)

        )



    def forward(self, img):

        feature = self.conv(img)

        output = self.fc(feature.view(img.shape[0], -1))

        return output





# 输出网格结构

net = LeNet()

print(net)



'''

训练过程:

    1、计算损失

    2、梯度清零

    3、回归

    4、更新所有参数(优化)

'''





def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):

    loss = torch.nn.CrossEntropyLoss()  # 交叉损失函数

    for i in range(num_epochs):

        train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time()

        for step, (batch_x, batch_y) in enumerate(train_iter):

            # training

            batch_x = batch_x.to(device)

            batch_y = batch_y.to(device)

            y_hat = net(batch_x)

            loss_ = loss(y_hat, batch_y)

            optimizer.zero_grad()

            loss_.backward()

            optimizer.step()

            train_l_sum += loss_.item()

            train_acc_sum += (y_hat.argmax(dim=1) == batch_y).sum().item()

            batch_count += 1

            n += batch_y.shape[0]

        print('epoch %d,loss %.4f,train acc %.3f,time %.1f sec'

              % (i + 1, train_l_sum / batch_count, train_acc_sum / n, time.time() - start))





# 损失函数

# 交叉熵失函数

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

print(device)



lr, num_epochs = 0.001, 5

optimizer = torch.optim.Adam(net.parameters(), lr=lr)

net.to(device)

train_ch5(net, train_iter,test_iter, batch_size, optimizer, device, num_epochs)



# 将训练好的模型保存为mnist.pkl

torch.save(net, 'mnist.pkl')



# 输出网络中的每一层的形状和参数

for param in net.parameters():

    print(param.shape, param.nelement())



# 导入模型,使用torch,load将上述训练好的模型导入

model = torch.load('mnist.pkl')

model.eval()



# 使用训练好的模型进行测试

test_acc_sum, n = 0, 0

for test_x, test_y in test_iter:

    test_x = test_x.to(device)

    test_y = test_y.to(device)

    y_hat = model(test_x)

    test_acc_sum += (y_hat.argmax(dim=1) == test_y).sum().item()

    n += test_y.shape[0]

print('test acc %.3f' % (test_acc_sum / n))



batch = next(iter(test_iter))

test_x, test_y = batch

print(test_x.shape)

grid = torchvision.utils.make_grid(test_x[0], nrow=1)

plt.figure(figsize=(8,8))

plt.imshow(np.transpose(test_x[0], (1, 2, 0)), cmap='gray')

print('labels;', test_y[0])



test_x = test_x.to(device)

test_y = test_y.to(device)

print(test_x[0].shape)

y_hat = net(test_x[0].reshape([1,1,28,28]))

print(y_hat[0], y_hat.argmax(dim=1)[0])

五、实验结果

六、实验总结

数据集准备是实验的基础。在这个阶段,需要收集一定量的手写字体样本,并进行预处理,以适应后续的实验。数据集的质量和数量都会影响实验的准确率和性能。

特征提取是手写字体识别的关键步骤。在这个阶段,需要使用一种或多种特征提取方法,从预处理后的图像中提取出有意义的特征。不同的特征提取方法适用于不同的手写字体风格,需要根据实际情况进行选择和调整。

模型训练是实验的核心。在这个阶段,需要使用提取的特征训练分类器,实现对手写字体的识别。常用的分类器包括支持向量机(SVM)、神经网络等。模型训练的效果直接影响到实验的准确率和性能。

模型评估是实验的重要环节。在这个阶段,需要使用测试集对模型进行评估,计算模型的准确率、召回率等指标,以了解模型的性能如何,以及模型是否能够正确识别手写字体。通过模型评估,可以发现模型存在的问题和不足,并进行优化改进。

模型优化是实验的必要步骤。如果模型的性能不满意,需要进行模型优化。这可能包括调整模型的参数、改进特征提取方法等。通过优化模型,可以提高模型的性能,提高手写字体识别的准确率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值