系列文章目录
机器学习笔记——梯度下降、反向传播
机器学习笔记——用pytorch实现线性回归
机器学习笔记——pytorch实现逻辑斯蒂回归Logistic regression
机器学习笔记——多层线性(回归)模型 Multilevel (Linear Regression) Model
深度学习笔记——pytorch构造数据集 Dataset and Dataloader
深度学习笔记——pytorch解决多分类问题 Multi-Class Classification
深度学习笔记——pytorch实现卷积神经网络CNN
深度学习笔记——卷积神经网络CNN进阶
深度学习笔记——循环神经网络 RNN
深度学习笔记——pytorch实现GRU
文章目录
前言
一、卷积神经网络(Convolutional Neural Networks)
在全连接神经网络下,由于我们直接将数据压缩,所以会损失数据的空间关系等信息。于是卷积神经网络先提取数据的特征,保留数据一部分的位置信息,进行计算、再提取特征、再计算…最后通过全连接层进行处理输出结果。
假设有这样一张图片,其通道数为channel=3,宽width,高heigh。指定一个c,w,h的patch,通过patch遍历这个图像。
1.单通道图像
例如,这里有一个5✖5的单通道(单层)图像;patch为单通道,大小为3✖3;卷积核kernel为单通道,大小为3✖3。patch从图像的左上角遍历图像,patch覆盖的图像部分与卷积核kernel做数乘运算。注意:不是做矩阵相乘运算,而是对应的位置的数相乘,最后相加。
例如,第一次patch与卷积核kernel数乘得到211,填入到输出矩阵中,而后patch向右移一格,新的patch矩阵又与卷积核kernel做数乘运算,得到295,填入到输出矩阵中。
依次类推,最后得到我们的输出矩阵
2.多通道图像
我们已经知道了单通道(单层)图像如何进行卷积计算
以三通道(三层)的图像为例,仍旧选取3✖3的patch,每一个通道的图像分别对应一个卷积核kernel,按照上述的方式进行卷积,分别得到三个输出矩阵,最后将三个矩阵相加就得到了最终的输出矩阵。
三通道(三层)的图像,通过三通道(三层)的卷积核,得到一个单通道(单层)的矩阵。
n个通道(n层)的图像,可以通过n个通道(n层)的卷积核,可以得到一个单通道(单层)的输出矩阵。
那么如何得到一个多通道(多层)的输出矩阵呢?
一张n个通道的图像,可以通过一个n通道的卷积核得到一个单通道的输出矩阵,那么用这张图像通过m个n通道的卷积核,就可以得到m个单通道的输出矩阵。
这要求我们的卷积核是一个四维的张量,m代表个数,n代表通道数,以及宽度和长度。
#!/user/bin/env python3
# -*- coding: utf-8 -*-
import torch
in_channels, out_channels = 5, 10 # 输入通道数,输出通道数
width, height = 100, 100 # 输入矩阵的宽高
batch_size = 1
kernel_size = 3 # 卷积核的大小----3*3的矩阵
# 用torch产生一个随机矩阵,当做输入
input = torch.randn(batch_size, in_channels, width, height)
# 卷积层
conv_layer = torch.nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size)
# 计算
output = conv_layer(input)
# 输出
print(input.shape) # 输入矩阵的形状
print(output.shape) # 输出矩阵的形状
print(conv_layer.weight.shape) # 卷积核矩阵的形状```
# 二、使用步骤
## 1.引入库
>代码如下(示例):
```c
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
输出结果:
输出结果解析:
输入矩阵的batch_size=1,通道数c=5,宽width=100,高height=100.
输出矩阵的batch_size=1,通道数c=10,宽width=98,高height=98.因为卷积核矩阵是3*3的,所以宽和高会减少2.
卷积核矩阵的个数m=10,通道数c=5,宽width=3,高height=3.
卷积核矩阵的通道数必须和输入矩阵的通道数相同,卷积核矩阵的个数决定输出矩阵的通道数。
3.扩充
如果我们想要输出矩阵的大小和输入的图像矩阵大小相同,可以在外围填充0.
上述图片的实现代码:
import torch
input = [3, 4, 6, 5, 7,
2, 4, 6, 8, 2,
1, 6, 7, 8, 4,
9, 7, 4, 6, 2,
3, 7, 5, 4, 1]
# 将输入转为张量,并转为矩阵
input = torch.Tensor(input).view(1, 1, 5, 5) # batch_size,channel,width,height
# 卷积层
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1,
bias=False) # 输入通道=1,输出通道=1,卷积核矩阵=3*3,padding=1 即给输入矩阵填充一圈0,不要偏置量
# 自定义卷积矩阵kernel
kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3) # 个数为1,输入矩阵通道为1,width=3,height=3
conv_layer.weight.data = kernel.data
# 计算
output = conv_layer(input)
# 输出
print(output)
print(output.shape)
运行结果:
4.设置步长
如果我们设置步长stride=2,那么patch矩阵每次会向右移动两格,得到一个更小的输出矩阵
import torch
input = [3, 4, 6, 5, 7,
2, 4, 6, 8, 2,
1, 6, 7, 8, 4,
9, 7, 4, 6, 2,
3, 7, 5, 4, 1]
# 将输入转为张量,并转为矩阵
input = torch.Tensor(input).view(1, 1, 5, 5) # batch_size,channel,width,height
# 卷积层
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, stride=2,
bias=False) # 输入通道=1,输出通道=1,卷积核矩阵=3*3,padding=1 即给输入矩阵填充一圈0,不要偏置量
# 自定义卷积矩阵kernel
kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3) # 个数为1,输入矩阵通道为1,width=3,height=3
conv_layer.weight.data = kernel.data
# 计算
output = conv_layer(input)
# 输出
print(output)
print(output.shape)
运行结果:
5.下采样——最大池化层max pooling
如图,我们选择一个22的maxpooling,它会将输入矩阵分成若干个22大小的矩阵,每个矩阵取其中最大的数,形成新的矩阵。
代码:
import torch
input = [3, 4, 6, 5,
2, 4, 6, 8,
1, 6, 7, 8,
9, 7, 4, 6]
# 将输入转为张量,再转为指定大小的矩阵
input = torch.Tensor(input).view(1, 1, 4, 4) # batch_size=1,c=1,width=1,h=1
# 池化层
maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)
# 计算
output = maxpooling_layer(input)
# 输出
print(output)
运行结果:
二.代码
1.分析
2.代码
import torch
from torchvision import datasets
from torchvision import transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
batch_size = 64
# 图像预处理
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
# 数据集
train_data = datasets.MNIST(root='mnist/', train=True, download=True, transform=transform)
test_data = datasets.MNIST(root='mnist/', train=False, download=True, transform=transform)
# 数据装载
train_batch = DataLoader(train_data, batch_size=batch_size, shuffle=True)
test_batch = DataLoader(test_data, batch_size=batch_size, shuffle=False)
# 模型
class CNNModel(torch.nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5) # 卷积层1
self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5) # 卷积层2
self.pooling = torch.nn.MaxPool2d(2) # 池化层
self.activate = torch.nn.ReLU() # 激活函数
self.linear = torch.nn.Linear(320, 10) # 线性层
def forward(self, x):
batch_size = x.size(0)
x = self.activate(self.pooling(self.conv1(x)))
x = self.activate(self.pooling(self.conv2(x)))
x = x.view(batch_size, -1) # 将矩阵变形,变成(batch_size,320)形状
x = self.linear(x)
return x
model = CNNModel()
# 让gpu进行运算
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device) # 将模型数据传给gpu
# 损失函数
criterion = torch.nn.CrossEntropyLoss()
# 优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# 可视化数据
epoch_list = []
accuracy_list = []
# 训练
def model_train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_batch, 1):
inputs, targets = data
inputs, targets = inputs.to(device), targets.to(device) # 将输入数据传入gpu
optimizer.zero_grad()
# forward
pred = model(inputs)
loss = criterion(pred, targets)
# backward
loss.backward()
# update
optimizer.step()
# 输出
running_loss += loss.item()
print('epoch:%d,loss=%.4f' % (epoch, running_loss / batch_idx))
running_loss = 0.0
# 测试
def model_test():
correct = 0
total = 0
with torch.no_grad():
for (inputs, targets) in test_batch:
inputs, targets = inputs.to(device), targets.to(device)
pred = model(inputs)
_, predicted = torch.max(pred.data, dim=1)
total += targets.size(0)
correct += (predicted == targets).sum().item()
print('Accuracy on test set:%d %%' % (100 * correct / total))
return correct / total
if __name__ == '__main__':
for epoch in range(10):
epoch_list.append(epoch)
model_train(epoch)
accuracy = model_test()
accuracy_list.append(accuracy)
# 绘图
plt.plot(epoch_list, accuracy_list)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()
3.运行结果