深度神经网络(使用CNN,NN,RNN,与KNN,SVM)

2023-11-09

深度神经网络

实验目的

  1. 了解神经网络结构(NN,CNN,RNN)
  2. 使用框架运行神经网络,查看并对比神经网络学习的效果
  3. 不断调整神经网络的参数,逐步提升学习效果(以CNN为例)
  4. 对比神经网络与一般机器算法的区别

目录

  • pytorch的安装
  • 数据预处理
  • CNN的实现
  • CNN的三次迭代过程及最终结果
  • RNN的实现与预测结果
  • NN的实现与最终结果
  • SVM的实现与最终结果

pytorch的安装

搭建环境为:Ubuntu18.04 + Anaconda
在官网上找到

在终端执行
conda install pytorch torchvision cpuonly -c pytorch

安装过程中可能会出现卡顿,可将conda的源换成清华镜像即可流畅下载
顺序执行


conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/

数据预处理

得到CIFA10数据

pytorch可以使用

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)

很方便的得到数据并保存在工作目录./data
注意到参数transform=transform,这一步目的在于对数据进行一定的处理以便得到更好的训练效果

这里使用的tansform函数是这样的:

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

首先把数据转化为“张量”形式,在通过Normalize把数据标准化,这里0.5是一个非常不准确的估量值,后期对模型进行优化时会对这里进行修正。

数据装载

pytorch处理数据统一使用dataloader这个概念,这里,我们也把训练集和测试集分别装载到dataloader中准备使用

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=5000, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

数据peek

在正式建立CNN之前,我们简单看一看CIFAR10的数据

dataiter = iter(trainloader)
images, labels = dataiter.next()
print(images.shape)
print(labels.shape)

输出:

我们就知道,CIFAR10的数据有两部分数据组成,一部分为33232的照片,另一部分一维的标签向量。

CNN的实现

定义一个卷积神经网络

在pytorch中搭建神经网络非常非常简单,官方的tutorial中给出了最简单的CNN结构:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))  # 第一层卷积
        x = self.pool(F.relu(self.conv2(x)))  # 第二层卷积
        x = x.view(-1, 16 * 5 * 5)            # 展平数据
        x = F.relu(self.fc1(x))               
        x = F.relu(self.fc2(x))               
        x = self.fc3(x)                       # 全连接层
        return x


net = Net()

优化函数和损失函数

然后,给出优化函数和损失函数:

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

这里分别使用交叉熵损失函数,使用随机梯度下降作为优化方法

训练网络

for epoch in range(2): 

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data

        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 2000 == 1999:
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

这里关键代码在7 ~ 11行,依次:

  • 清空梯度值
  • 使用net输出结果
  • 计算loss
  • loss反向传播计算梯度
  • 更新参数

同时,每2000个数据输出loss

检测模型

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

这里代码非常简单,检测网络在测试集的效果:

运行结果

可以看到运行结果为百分之54,还算不错。
这样,我们就完成了一个CNN神经网络从定义到训练再到预测的全过程,接下来,为了提升模型的预测准确率,我们不断调试模型的参数,对模型进行三次迭代

CNN的三次迭代过程及最终结果

迭代一:增加验证集,调整学习率,更改transform

首先,把训练集切分为2:8,两部分,其中8,用来训练,2用来训练中判断预测准确率,方便及时调整学习率,避免过拟合。

dataset_size = len(trainset)
indices = list(range(dataset_size))
split = int(np.floor(0.2 * dataset_size))
np.random.seed(42)
np.random.shuffle(indices)
train_indices, val_indices = indices[split:], indices[:split]
train_sampler = torch.utils.data.SubsetRandomSampler(train_indices)
valid_sampler = torch.utils.data.SubsetRandomSampler(val_indices)

在构造训练集和验证集时,添加sampler参数,即可分割成功

trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, sampler=train_sampler, num_workers=2)
validation_loader = torch.utils.data.DataLoader(trainset, batch_size=4, sampler=valid_sampler)

我们在输出loss时同时输出网络在验证集的预测准确率:

if i % 2000 == 1999: 
            print('[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))
            with torch.no_grad():
                for data in validation_loader:
                    images, labels = data
                    outputs = net(images)
                    _, predicted = torch.max(outputs.data, 1)
                    total += labels.size(0)
                    correct += (predicted == labels).sum().item()

            print('Accuracy of the network on the  valid images: %d %%' % (100 * correct / total))
            running_loss = 0.0

这时,我们就可以在输出时看到实时的预测准确率:

经过长长长长长长长长长长长长长长长时间的等待,发现在lr=0.001,训练轮数超过20后虽然loss在减少,但是准确率不再增加,再经过几次执行,发现lr=0.01,轮数为10时模型可以及时收敛同时预测效果未受到影响。

其次,tutorial中给出的transform不是很标准,这里结合博客中的经验,把转换函数改为:

transform_train = transforms.Compose([  	
    transforms.RandomCrop(32, padding=4),   
    transforms.RandomHorizontalFlip(),      
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)), 
])

对图片数据进行一定的预处理,使得feature更加明显易学习。
经过这一轮的迭代,预测准确率来到了62%

迭代二:增加卷积层数,更改卷积结构,kernel size与batch size

另一个尝试是更改神经网络的结构,调整每一层卷积的channel数,同时增加多层卷积,减少全连接层数等:

def __init__(self):
        super(Net, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2, 2)
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2,2)
        )
        self.layer3 = nn.Sequential(
            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.MaxPool2d(2,2)
        )
        self.fc1 = nn.Linear(4 * 4 * 128, 10)
    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = x.view(-1, 128*4*4)
        x = self.fc1(x)
        return x

在这里花费了大量的时间,甚至一度增加了数十层网络,但是最后还是回到最初的起点,三层神经网络,同时加上BatchNorm2d对每层的batch归一化。
这次迭代对预测提升很大,准确率第一次达到了 75%+

迭代三:更换激活函数,池化函数,优化函数,损失函数……

第三次迭代更多的是提供了一个思考方向,因为这次虽然也做了许多许多尝试,但是并没有对最终结果有显著的提升。
主要的更改在,改用Adam作为优化函数

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

关于优化器的选择,主要参考了这篇文章
https://zhuanlan.zhihu.com/p/22252270

而关于激活函数,做了N多次尝试,最终还是回到RELU。(激活函数的不同及选择总结在了这篇文章内https://blog.csdn.net/weixin_41075215/article/details/103400500)

同样的,不同的池化函数,优化函数与损失函数,都稍微做了一些更改,但是没有得到更好的结果,所以没有进一步深入地探究他们对模型的影响
这一轮迭代对最终结果影响不大,准确率依旧维持在 76 ~ 78% 左右

RNN的实现与预测结果

对于RNN,只是构建了一个最简单的模型,并没有对其参数进行太多的更改与优化。
网络定义如下:

class RNN(nn.Module):
    def __init__(self):
        super(RNN, self).__init__()

        self.rnn = nn.LSTM(         
            input_size=32*3,
            hidden_size=64,         
            num_layers=1,           
            batch_first=True,
        )

        self.out = nn.Linear(64, 10)

    def forward(self, x):
        r_out, (h_n, h_c) = self.rnn(x, None)   # None represents zero initial hidden state
        out = self.out(r_out[:, -1, :])
        return out
net = RNN()

这里我以图片的每一行为一个时间序列,则每次的input size就是每一行(32*3)。
同时在模型的选择上,比较RNN和LSTM后选择LSTM作为神经网络的模型,因为如果直接选择RNN的话,结果会很差。
预测结果:
验证集:

测试集:

可以看出,模型在验证集中表现一般,但至少可以达到40 ~ 50%,而在测试集中表现极差,始终未超过20%,出现这种情况的原因,我猜测是由于RNN神经网络的特性造成的,RNN考虑每层数据多个节点之间的关系,可能训练集和测试集在这种特征上不尽相同,导致模型学到了一些本不该学到的东西,使其泛化能力不再增强

NN的实现与预测结果

定义七层全连接神经网络如下:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Linear(3*32*32, 256),
            nn.ReLU(),
            nn.Dropout(0.1)
        )
        self.layer2 = nn.Sequential(
            nn.Linear(256, 500),
            nn.Dropout(0.1)
        )
        self.layer3 = nn.Sequential(
            nn.Linear(500, 500),
            nn.ReLU(),
        )
        self.layer4 = nn.Sequential(
            nn.Linear(500, 256),
            nn.ReLU(),	
            nn.Dropout(0.5)
        )
        self.layer5 = nn.Sequential(
            nn.Linear(256, 256),
            nn.ReLU(),
            nn.Dropout(0.5)
        )
        self.layer6 = nn.Sequential(
            nn.Linear(256, 128),
            nn.ReLU(),
        ) 
        self.fc1 = nn.Linear(128, 10)
    def forward(self, x):
        x = x.view(x.size(0), -1)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.layer5(x)
        x = self.layer6(x)
        
        #x = x.view(-1, 256*2*2)
        x = self.fc1(x)
        return x

这里主要考虑的就是两个问题,一个是使用多少层网络?另一个就是每层的结构是怎样的?参考几篇博客后我选择七层神经网络,同时在某些层上添加Dropout以期去掉死神经元,最终预测结果如下


可见,普通的全连接网络,在图片分类问题上相比RNN泛化能力要更强一些。

机器学习

这里分别使用sikilearn的SVM和KNN来学习。
代码如下:

# batch size分别未5000和100
# 一次取出全部数据 
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=5000, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

dataiter = iter(trainloader)
images, labels = dataiter.next()
print(images.shape)
print(labels.shape)
images = images.view(5000, -1)
images = list(images.numpy())          #将数据由Tensor转为Numpy后转成list数组 
labels = list(labels.numpy())

dataiter_test = iter(testloader)
images_test, labels_test = dataiter_test.next()
images_test = images_test.view(100, -1)
images_test = list(images_test.numpy())
labels_test = list(labels_test.numpy())

model = svm.SVC()
# model = neighbors.KNeighborsClassifier(n_neighbors=15)
model.fit(images, labels)
score = model.score(images_test, labels_test)
print(score)

sklearn的模型封装的非常好,代码仅仅在处理数据上,主要是使用loader把数据一次取出(但是50000数据量太大,仅使用5000进行训练,100进行预测)
预测结果如下

SVM

KNN

由此可见,普通的机器学习算法在处理图片分类上不一定比神经网络要差,选取合适的模型甚至比RNN的预测结果要好上不少

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度神经网络(使用CNN,NN,RNN,与KNN,SVM) 的相关文章

  • Anaconda入门基本操作

    文章目录 1 配置环境变量 2 基础操作 2 1 activate 2 2 创建自己的虚拟环境 2 3 切换环境 3 安装 卸载第三方包 4 查看环境包信息 5 导入导出环境 6 删除环境 慎用 7 总结当前命令 1 配置环境变量 如果是w
  • 数据仓库实施

    文章目录 一 数据分析挖掘过程 1 数据获取 2 数据处理 3 数据建模 4 模型评价 5 数据可视化 二 ETL过程 1 数据特征 2 过程描述 3 ETL 1 数据抽取 2 数据清洗 3 数据转换 4 数据加载和索引 4 kettle
  • git项目管理,这些就够了

    环境 ubuntu16 04 参考 https baijiahao baidu com s id 1621620608602705821 wfr spider for pc https www cnblogs com Sharley p 6
  • 关于前端在一个选择框中选择多个内容的操作

    直接上效果图 以上效果为 可选择多个内容放在框里 再作相应操作将内容传给后端 一 在html的body的form表单下码一个div
  • qt usb热插拔,windows版本,环境qt5.12.9和win10

    写文章的目的 自己要做windows上的usb通信 但是找遍全网都没找到完整的 虽然有热插拔相关的 但是热插拔的监测不够全面 基本都是只能监测部分的插拔 并且大家都推荐使用libusb库 但是使用了一下该库 哎哟我去 暂时还不支持windo
  • linux中shell的小括号、大括号的用法区别

    Linux中小括号 和大括号 都是对其中的一串命令进行执行 但有一定的区别 其区别如下 1 小括号 命令组 括号中的命令新开一个子shell程序 括号中的变量为本地变量 不能够在脚本其他部分使用 括号中多个命令之间用分号隔开 备注 在括号中
  • ffmpeg推流命令

    ffmpeg re i xxx mp4 vcodec copy acodec copy f flv y rtmpurl re 按照帧率发送 如果不加 手册里说的是发送as fast as possible i 输入 vcodec copy

随机推荐

  • 100天精通Python(进阶篇)——第42天:pdfplumber读取pdf(基础+代码实战写入Excel)

    文章目录 一 Python操作PDF 13大库对比 二 pdfplumber模块 1 安装 2 加载PDF 3 pdfplumber PDF类 4 pdfplumber Page类 三 实战操作 1 提取单个PDF全部页数 2 批量提取多个
  • LeetCode:217(Python)—— 存在重复元素(简单)

    存在重复元素 概述 给你一个整数数组 nums 如果任一值在数组中出现 至少两次 返回 true 如果数组中每个元素互不相同 返回 false 输入 nums 1 2 3 1 输出 true 输入 nums 1 2 3 4 输出 false
  • JS面试题

    1 es6新特性 let和const关键字 箭头函数 多行字符串 解构赋值 Promises let声明变量和const声明常量 变量不能重复声明 都是块级作用域 不存在变量提升 箭头函数 es6提供了简洁的箭头函数语法 可以更简单的定义函
  • python与爬虫的关系_python为什么叫爬虫?有什么关系?

    今天 小编听到有人问 Python为什么叫爬虫 我想很多人对于这个问题都很好奇 甚至对于Python和爬虫的概念模糊 今天小编通过这篇文章为大家详细解答一下 Python与爬虫有什么关系 爬虫一般是指网络资源的抓取 因为Python的脚本特
  • 误删li64.so.6,如何恢复

    遇到下面这种情况 误删li64 so 6还原方案 第一步 先关掉虚拟机 右键找到电源后选择打开电源时进入固件 进入Boot界面 第二步 使用shift 将光盘启动优先 然后切至exit保存退出 第三步 来到重启界面后 选择Troublesh
  • 微信小程序的五种传值方式

    1 使用全局变量传递数据 利用app js 中的 globalData 将数据存储为全局变量 在需要使用的页面通过getApp globalData获取数据 app js App globalData data name demo 使用组件
  • < Linux >:Linux 进程概念 (4)

    目录 五 孤儿进程 六 进程优先级 6 1 基本概念 6 2 查看时实系统进程 6 3 PRI and NI 七 其他概念 四 X 状态 死亡状态 对应于各个操作系统下的进程状态中的进程终止 退出 态 所谓进程处于 X 状态 死亡状态 代表
  • 【HTML】讲讲HTML5视频播放的方式

    HTML 讲讲HTML5视频播放的方式 引言 github HTML 讲讲HTML5视频播放的方式 内容速递 看了本文您能了解到的知识 想要网页播放视频再也不需要使用插件了 HTML本身就支持 而且更加稳定 上节讲了HTML5的音频播放 和
  • 7.14资产收集-灯塔

    sql注入 xss 源码泄露 redis未授权访问 逻辑漏洞 支付漏洞 GitHub TophantTechnology ARL ARL Asset Reconnaissance Lighthouse 资产侦察灯塔系统旨在快速侦察与目标关联
  • 在matlab中如何使用SVM工具箱

    一 SVM下载 http see xidian edu cn faculty chzheng bishe indexfiles indexl htm 二 在MATLAB中添加svm工具箱 参考 http jingyan baidu com
  • 银行业法律法规与综合能力 第五章 银行监管与自律 10%

    第五章 银行监管与自律 考点1 银行监管体制 考点2 银行自律与市场约束 考点3 职业操守与行为准则 考点4 清廉金融 考点5 银行业消费者杈益保护 考点1 银行监管体制 一 银行监管起源与演变 1 英国颁布的 反泡沫公司法 标志着世界金融
  • 小程序---云函数npm install报错

    问题 云函数右键菜单 在外部终端窗口中打开 npm install报错 解决方法 使用cnpm install 安装依赖
  • error:03000086:digital envelope routines::initialization error

    项目背景 前端vue项目启动突然报错error 03000086 digital envelope routines initialization error 我用的开发工具是vscode node版本是v18 17 0 前端项目版本如下
  • redis安装、配置、启动

    一 redis默认安装位置 usr local bin redis benchmark 性能测试工具 可以在自己本子运行 看看自己本子性能如何 服务启动起来后执行redis check aof 修复有问题的AOF文件redis check
  • mac安装VMware Fusion及虚拟Windows注意事项

    mac安装VMware Fusion及虚拟Windows注意事项 文章目录 mac安装VMware Fusion及虚拟Windows注意事项 1 前言及注意事项 2 VMWare Fusion下载及安装 3 安装虚拟Windows 4 Vi
  • 代码覆盖率

    在做单元测试时 代码覆盖率常常被拿来作为衡量测试好坏的指标 甚至 用代码覆盖率来考核测试任务完成情况 比如 代码覆盖率必须达到80 或 90 于是乎 测试人员费尽心思设计案例覆盖代码 用代码覆盖率来衡量 有利也有有弊 本文我们就代码覆盖率展
  • viewPager + ConstraintLayout 自适应高度

    在 ConstraintLayout 约束布局 中 我们发现viewPager除了设置固定的尺寸外 要不就是全屏 这很不符合我们的需求 改造下 layout中
  • Pandas常用统计数据方法

    import pandas as pd 1 准备数据 假设有 5 个人 分别参加了 4 门课程 获得了对应的分数 同时这个 5 个人分别负责的项目个数 在 Project num 列中显示 data name pd Series Alice
  • Linux 用户管理与文件权限

    Linux 是一个多用户系统 它允许多个用户同时登陆主机 并为他们分配不同的资源和工作环境进行使用 当然 不同的用户都有文件的私有需求 所以设置不同用户文件的权限管理十分重要 01 用户与用户组 Linux 中一般将文件访问权限的身份分为三
  • 深度神经网络(使用CNN,NN,RNN,与KNN,SVM)

    深度神经网络 实验目的 了解神经网络结构 NN CNN RNN 使用框架运行神经网络 查看并对比神经网络学习的效果 不断调整神经网络的参数 逐步提升学习效果 以CNN为例 对比神经网络与一般机器算法的区别 目录 pytorch的安装 数据预