机器学习/人工智能 实验二:图像特征自动学习方法实践与分析

news2024/11/26 18:34:15

写在前面

参考的是https://zh.d2l.ai/index.html

一、实验目的与要求

(1)利用基于深度学习的特征自动学习方法完成图像特征提取的实验方案的设计。
(2)编程并利用相关软件完成实验测试,得到实验结果。
(3)通过对实验数据的分析、整理,得出实验结论,培养学生创新思维和编写实验报告的能力,以及处理一般工程设计技术问题的初步能力及实事求是的科学态度。
(4)利用实验更加直观、方便和易于操作的优势,提高学生学习兴趣,让学生自主发挥设计和实施实验发挥出学生潜在的积极性和创造性。

二、实验内容

(1)采用已经学过的深度特征提取方法,如卷积神经网络( CNN )等实现图像特征提取和学习的任务。
(2)分析比较深度学习方法的优缺点。

三、实验设备与环境

Windows11系统、Anaconda3、Pycharm Community、Jupyter Notebook、Scikit-learn库、TensorFlow深度学习框架、Pytorch深度学习框架

四、设计正文

(包括分析与设计思路、各模块流程图以及带注释的主要算法源码,若有改进或者创新,请描述清楚,并在实验结果分析中对比改进前后的结果并进行分析)

4.1 分析与设计思路

卷积神经网络是含有卷积层的神经网络,常用来处理图像数据。
卷积运算用星号表示。卷积的第一个参数为输入,第二个参数被称为核函数。输出为特征映射。将一张二维的图像 I I I作为输入,用一个二维的核 K K K,则:
S ( i , j ) = ( I ∗ K ) ( i , j ) = ∑ m ∑ n I ( m , n ) K ( i − m , j − n ) S(i,j)=(I\ast K)(i,j)=\sum_m\sum_n I(m,n)K(i-m,j-n) S(i,j)=(IK)(i,j)=mnI(m,n)K(im,jn)
实际上,在深度学习领域的“卷积”都是指互相关运算。二维卷积层输出的二维数组可以看做输入在空间维度上某一级的表征(特征图)。假设输入的形状是 n h ∗ n w n_h*n_w nhnw,卷积核窗口形状是 k h ∗ k w k_h*k_w khkw,在步长为1的情况下,则输出形状是 ( n h − k h + 1 ) ( n w − k w + 1 ) (n_h-k_h+1)(n_w-k_w+1) (nhkh+1)(nwkw+1)
填充(padding)是指在输入高和宽的两侧填充元素(0元素)。如果在高的两侧填充 p h p_h ph行,在宽的两侧填充 p w p_w pw列,则输出形状将变成:
( n h − k h + p h + 1 ) ( n w − k w + p w + 1 ) (n_h-k_h+p_h+1)(n_w-k_w+p_w+1) (nhkh+ph+1)(nwkw+pw+1)
使用更大的步长时,若高上步长 s h s_h sh,宽上步长 s w s_w sw,则输出形状为:
⌊ ( n h − k h + p h + 1 ) / s h ⌋ ⌊ ( n w − k w + p w + 1 ) / s w ⌋ \lfloor (n_h-k_h+p_h+1)/s_h\rfloor\lfloor(n_w-k_w+p_w+1)/s_w\rfloor ⌊(nhkh+ph+1)/sh⌊(nwkw+pw+1)/sw
对于彩色图像,可以有多个输入通道和多个输出通道。在做互相关运算时,每个输出通道上的结果由卷积核在该输出通道上的核数组与整个输入数组计算而来。
同卷积层一样,池化层每次对输入数据有一个固定形状窗口(池化窗口)。不同于卷积层内计算输入和核的互相关性,池化层直接计算池化窗口内元素的最大值或平均值。同卷积层一样,池化层也可以在输入的高和宽的两侧填充并调整窗口的移动步幅改变输出形状。在处理多通道输入数据时,池化层对每个输入通道分别池化,而不像卷积层那样将各通道输入按通道相加。所以池化层输出通道数和输入通道数相等。
在本次实验中,使用经典的LeNet卷积神经网络。LeNet分为卷积层块和全连接层块两个部分。卷积层块的基本单位是卷积层后接最大池化层。卷积层用来识别图像里的空间模式如线条或物体局部,之后的最大池化层用来降低卷积层对位置的敏感性。卷积层块由两个这样的基本单位重复堆叠构成,在卷积层块中每个卷积层使用5*5的窗口,并在输出上使用sigmoid激活函数。第一个卷积层输出通道数为6,第二个卷积层输出通道数增加到16。卷积层和两个最大池化层窗口均为2*2,且步长为2。所以池化窗口每次滑动所覆盖区域互不重叠。在将卷积层块的输出送入全连接层块前,全连接层块会将小批量中每个样本变平。全连接层输入性状将变成二维,第一维是小批量中的样本,第二维是每个样本变平后的向量表示,且向量长度为通道宽的积。全连接层块含3个全连接层,输出个数分别是120、84、10,其中10位输出的类别个数。
LeNet卷积神经网络的整体流程如下:
在这里插入图片描述
在本次实验中,使用经典的Fashion-MNIST数据集进行测试。

4.2 主要算法源码

import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import torch
from torch import nn
from d2l import torch as d2l
net = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),#卷积
    nn.AvgPool2d(kernel_size=2, stride=2),#平均池化
    nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),#卷积
    nn.AvgPool2d(kernel_size=2, stride=2),#平均池化
    nn.Flatten(),#展平
    nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),#全连接
    nn.Linear(120, 84), nn.Sigmoid(),#全连接
    nn.Linear(84, 10))#全连接
X = torch.rand(size=(1, 1, 28, 28), dtype=torch.float32)#随机初始化种子
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape: \t',X.shape)
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)#读取训练集并batch
def evaluate_accuracy_gpu(net, data_iter, device=None): #@save
    """使用GPU计算模型在数据集上的精度"""
    if isinstance(net, nn.Module):
        net.eval()  # 设置为评估模式
        if not device:
            device = next(iter(net.parameters())).device
    # 正确预测的数量,总预测的数量
    metric = d2l.Accumulator(2)
    with torch.no_grad():
        for X, y in data_iter:
            if isinstance(X, list):
                # BERT微调
                X = [x.to(device) for x in X]
            else:
                X = X.to(device)
            y = y.to(device)
            metric.add(d2l.accuracy(net(X), y), y.numel())
    return metric[0] / metric[1]#计算accuracy
#@save
def train_ch6(net, train_iter, test_iter, num_epochs, lr, device):
    """用GPU训练模型(在第六章定义)"""
    def init_weights(m):
        if type(m) == nn.Linear or type(m) == nn.Conv2d:
            nn.init.xavier_uniform_(m.weight)
    net.apply(init_weights)
    print('training on', device)
    net.to(device)
    optimizer = torch.optim.SGD(net.parameters(), lr=lr)#LR优化器
    loss = nn.CrossEntropyLoss()#交叉熵损失函数
    animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],
                            legend=['train loss', 'train acc', 'test acc'])
    timer, num_batches = d2l.Timer(), len(train_iter)
    for epoch in range(num_epochs):
        # 训练损失之和,训练准确率之和,样本数
        metric = d2l.Accumulator(3)
        net.train()
        for i, (X, y) in enumerate(train_iter):
            timer.start()
            optimizer.zero_grad()
            X, y = X.to(device), y.to(device)
            y_hat = net(X)
            l = loss(y_hat, y)
            l.backward()
            optimizer.step()
            with torch.no_grad():
                metric.add(l * X.shape[0], d2l.accuracy(y_hat, y), X.shape[0])
            timer.stop()
            train_l = metric[0] / metric[2]
            train_acc = metric[1] / metric[2]
            if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:
                animator.add(epoch + (i + 1) / num_batches,
                             (train_l, train_acc, None))
        test_acc = evaluate_accuracy_gpu(net, test_iter)
        animator.add(epoch + 1, (None, None, test_acc))#展示曲线
        animator.show()
    print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
          f'test acc {test_acc:.3f}')
    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
          f'on {str(device)}')
lr, num_epochs = 0.9, 10
train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

五、实验结果及分析

程序输出数据如下

Conv2d output shape: 	 torch.Size([1, 6, 28, 28])
Sigmoid output shape: 	 torch.Size([1, 6, 28, 28])
AvgPool2d output shape: 	 torch.Size([1, 6, 14, 14])
Conv2d output shape: 	 torch.Size([1, 16, 10, 10])
Sigmoid output shape: 	 torch.Size([1, 16, 10, 10])
AvgPool2d output shape: 	 torch.Size([1, 16, 5, 5])
Flatten output shape: 	 torch.Size([1, 400])
Linear output shape: 	 torch.Size([1, 120])
Sigmoid output shape: 	 torch.Size([1, 120])
Linear output shape: 	 torch.Size([1, 84])
Sigmoid output shape: 	 torch.Size([1, 84])
Linear output shape: 	 torch.Size([1, 10])
training on cpu
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 350x250 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
<Figure size 1920x951 with 1 Axes>
loss 0.460, train acc 0.829, test acc 0.812
5569.6 examples/sec on cpu

可以看到,正确地建立了经典的LeNet模型,在cpu上进行训练,最终结果为交叉熵函数loss为0.460。在训练集上准确率为0.829,测试集上准确率为0.812。在cpu上训练,每一秒只能运行5569.6个训练数据。
Epoch了10次,Loss函数、训练集准确率、测试集准确率变化曲线如下图所示。
在这里插入图片描述

六、总结及进一步改进设想

(主要总结本实验的不足以及进一步改进的设想)
总结:在本次实验中,使用了经典的基于CNN的LeNet算法,实现了对图片自动的特征提取与分类。深度学习的特点是存在一个甚至多个隐藏层(Hidden Layers)。
所以,深度学习比起传统机器学习方法的优点是:有隐藏层,能自动学习并完成特征提取任务,对于图像、自然语言、语音等非结构化的数据集,能够自动进行特征提取而不需要我们手动地构造相关特征,完成比一个简单的Sigmoid/Softmax函数更多的学习任务。比起简单的多层感知机、神经网络,卷积神经网络能够保留输入形状的特征,将统一卷积核与不同位置的输入重复计算,避免隐藏层权重参数尺寸过大。在结果上,测试的精度比起传统机器学习算法也有一定提升。
然而,深度学习方法也有缺点。深度学习需要消耗大量的内存、运算资源、时间进行训练。
本实验存在一定不足之处,需要进一步改进。由于在安装Pytorch与TensorFlow深度学习框架时,安装成了cpu版本的而不是gpu版本的,所以在笔记本电脑上只能epoch较少次数且每个epoch都需要很长的耗时。因此,需要安装gpu版本,以更高效地学习深度学习,完成深度学习实验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity | 序列化(Serialized)和反序列化(NonSerialized)是什么意思

一、什么是序列化 官方叙述&#xff1a;序列化是将对象的状态信息转换为可以存储或传输的形式的过程。 人话叙述&#xff1a;我们平时输入的代码&#xff0c;实际上是不能储存或者传输的&#xff0c;所以我们需要翻译一下&#xff0c;翻译成能储存或者翻译的文字&#xff0c;这…

【SpringBoot 学习】52、SpringBoot 使用 grpc 实现远程服务调用

文章目录一、SpringBoot 使用 grpc 实现远程服务调用1、服务端编写2、客户端编写一、SpringBoot 使用 grpc 实现远程服务调用 gRPC 是一个现代的、开源的、高性能的远程过程调用&#xff08;RPC&#xff09;框架&#xff0c;可以在任何地方运行。gRPC 使客户端和服务器应用程序…

Java-Thread多线程的使用

Java-Thread多线程的使用一、线程&#xff0c;进程&#xff0c;并发&#xff0c;并行的概念1.进程2.线程3.并发和并行二、线程的创建和使用1.通过继承Thread类&#xff0c;重写run方法2.实现Runnable接口&#xff0c;重写run方法3.使用案例三、线程的常用方法四、线程的退出和中…

关于机器人状态估计(11)-VIO单目与双目/雷达Lidar SLAM/未来的机器人

写这篇文章的时候刚发生行业大事件&#xff1a; Google收购ROS 其实一开始还是水&#xff0c;绝对大量文不对题&#xff0c;但是必有干货&#xff0c;毕竟用的是这个关键的系列标题。 最近有几件行业内发生的大小事&#xff0c;让我觉得有必要更一下。 首先是Livox的mid-360…

VueUse(中文)——核心函数:State相关函数

VueUse官方地址 一、createGlobalState 将状态保持在全局范围内&#xff0c;以便跨Vue实例重用 1、没有持久性(存储在内存中) 例如&#xff1a; 或者 2、持久性存储 使用useStorage()存储在localStorage:例如&#xff1a; 组件使用&#xff1a; 二、createInjectionSt…

【图灵商城】前、后端项目搭建与运行

【图灵商城】前、后端项目搭建与运行 项目介绍 图灵商城-基础班架构图&#xff0c;如下所示&#xff1a; 本节是项目代码的初始化&#xff0c;今天是2023-01-15&#xff0c;先预祝大家新年快乐&#xff01;&#xff01;&#xff01; 图灵商城这个项目是一个前后端分离的项目…

我这是这样知道 React TS 中的 Event Handler 类型的

开头 现在 TypeScript 的发展也越来越成熟&#xff0c;已逐渐应用到我们开发的前端项目之中&#xff0c;它能够带来类型提示&#xff0c;提前规避类型上的错误&#xff0c;来提高项目代码的健壮性&#xff0c;以及更高效的编码效率&#xff0c;前提就是我们需要定义好相应的类…

创客匠人赋能线上瑜伽健身实现流量增长

近年来&#xff0c;我国的儿童、成年人肥胖率逐年攀升。身边发胖的人越来越多&#xff0c;尤其是步入中年的人群&#xff0c;很多都有“发福”的现象。 超重肥胖已经成为影响我国居民健康的重要公共卫生问题。在身材焦虑和疫情肆虐下&#xff0c;很多人开始重视自己的健康问题…

python学习笔记---Python基础【廖雪峰】

Python基础 数据类型和变量 整数 对于很大的数&#xff0c;例如10000000000&#xff0c;很难数清楚0的个数。Python允许在数字中间以_分隔&#xff0c;因此&#xff0c;写成10_000_000_000和10000000000是完全一样的。十六进制数也可以写成0xa1b2_c3d4。 >>> prin…

Qt opencv编译详细教程(windows版)

在Qt中使用opencv这个算法视觉库&#xff0c;前期环境步骤搭建如下&#xff1a; 1、下载cmake。 2、下载opencv库&#xff0c;我这里下载的是opencv-3.3.1版本。 3、没有安装Qt的下载Qt软件&#xff0c;Qt的环境安装部署&#xff0c;这里不做介绍。 4、安装cmake后&#xff0c;…

python学习笔记---IO编程【廖雪峰】

IO编程 ​ IO在计算机中指Input/Output&#xff0c;也就是输入和输出。由于程序和运行时数据是在内存中驻留&#xff0c;由CPU这个超快的计算核心来执行&#xff0c;涉及到数据交换的地方&#xff0c;通常是磁盘、网络等&#xff0c;就需要IO接口。 ​ IO编程中&#xff0c;S…

冒泡排序算法的实现和优化~

冒泡排序算法&#xff1a; 算法思想&#xff1a; 反复扫描待排序记录序列&#xff0c;在扫描的过程中&#xff0c;顺次比较相邻的两个元素的大小&#xff0c;若逆序就交换位置 文字描述该算法&#xff1a; 以升序为例&#xff1a; 依次比较数组中相邻两个元素大小&#xf…

win10+ubuntu23.04双系统安装

win10win10先安装好&#xff08;确保主板上各个螺丝稳定&#xff0c;至少4对螺丝铜柱&#xff0c;否则会各种蓝屏&#xff09;如果双系统安装失败了&#xff0c;连win10都进不去了&#xff0c;用原版ISO刻录的U盘或者光驱来修复引导。Easybcd安装Ubuntu23.04使用的ubuntu镜像文…

【项目实战】使用Java Keytool工具生成的CSR给第三方云平台签名

一、背景 客户要求我们提供一个CSR文件&#xff0c;给他们签名&#xff0c;他们的服务器是部署在Amazon上的。 二、Keytool是什么&#xff1f; Keytool 是一种 Java中的数字证书管理工具&#xff0c;用于管理密钥和证书。 它可以用来生成/申请数字证书、导入证书、导出证书、…

优秀的程序员是如何做好时间管理的

程序员是一项既消耗脑力&#xff0c;又消耗体力的职业&#xff0c;想成为一名成功的程序员&#xff0c;不仅要靠坚持不懈的努力&#xff0c;异于常人的天赋&#xff0c;更需要一套行之有效的时间管理方法&#xff0c;才能让自己在有限的时间内写出更好的代码&#xff0c;获得更…

用C语言图形库画一个红色爱心

这次我教大家用代码画一个心&#xff0c;这样你们就可以送给你们的女&#xff08;男&#xff09;朋友了。没找到对象的也可以用来表白啊。1.首先&#xff0c;我去百度找了心形线的函数&#xff0c;如下&#xff1a;2. 联系高中的数学知识&#xff0c;我们知道&#xff1a;f(x)&…

Unidbg模拟执行某段子so实操教程(二) LoadSo对比

一、目标 上篇文章里面&#xff0c;我们跑出来的结果有点不对头&#xff0c;多个一个 ABC。 这次我们试试用 LoadSo的方式来排查下问题。 参考&#xff1a; [借鸡生蛋之SandHook的使用(一)] 二、步骤 我们先用Android Studio 4.0 来编译一个so 打开AS&#xff0c;然后用向…

蓝桥杯STM32G431RBT6学习——按键

蓝桥杯STM32G431RBT6学习——按键 前言 按键同样为每年的必考考点&#xff0c;国信长天开发板中的按键电路如下&#xff1a; 芯片的PA0、PB0、PB1、PB2作为按键输入引脚&#xff0c;并采用外部上拉连接&#xff0c;当对应引脚检测到低电平时&#xff0c;即按键被按下。 STM…

【2293. 极大极小游戏】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#xff0c;如果 n 1 &#xff0c;终止 算法过程。否则&#xf…

【自学Docker】Docker环境命令

Docker info命令 Docker info命令概述 用于查看 docker 容器的基本信息。 Docker info命令语法 haicoder(www.haicoder.net)# docker info案例 查看所有信息 使用 docker info 命令&#xff0c;查看当前 docker容器 的所有的信息。 haicoder(www.haicoder.net)# docker …