目录
- 卷积运算
- 特征提取
- 同一层的某些神经元是权值共享
- 注意
- 代码
- 卷积过程
- 补充
- RNN神经网络
卷积运算
卷积运算是一种特征提取方式,卷积运算结果即为提取的特征,卷积核像一个筛子,将图像中符合条件(激活值越大越符合条件)的特征筛选出来。
卷积神经网络由卷积核而得名。
卷积核的作用就是把前一层输入的数据特征提取出来,
特征提取
通过一个线性计算映射和一个激励函数(可选),最后在最后一层成为一个数值形式的激励值。
如图输入一个55的图形,图形中的每个像素都是一个具体的数字,每个像素值为RGB具体表现。为了表示方便,用0代表黑色,用1代表白色,表示一个黑白图。用一个33的卷积核对其y=wx+b进行卷积,其中w=[1,0,1,0,1,0,1,0,1],就是11+01+11+01+11+01+10+00+1*1+0=4
这个4会被投射到后方的Feature Map中,就是卷积特征中左上角的点。
同一层的某些神经元是权值共享
注意
这不是矩阵乘法,是两个向量做点积
在这个例子,w=[1,0,1,0,1,0,1,0,1],b=0
在一次扫描后,卷积核会从左到右,从上到下扫描整幅图片,并将每次计算的结果放到convolved feature
如果一个Feature map要与前面的图片的尺寸保持一致,通常需要在边缘补0,这种操作叫做padding,
扫描过程是跳跃的,可以一次移动一个像素进行扫描。striding =1 如图,如果padding =2,得到的feature map与输入图片的尺寸是相同的。
代码
在代码中,Kernel Size是卷积核的尺寸,卷积核的数目叫做channel,就是使用多少个这样的卷积核对图片进行扫描。在训练的时候使用梯度下降找出各个卷积核的w取什么值的时候模型有更好的表现,一般来说,卷积网络需要的数量比全连接网络更少,训练速度更快,泛化能力更强。
卷积过程
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
num_epochs = 5
num_classes = 10
batch_size = 100
learning_rate = 0.001
train_dataset = torchvision.datasets.MNIST(root='../../data/',train=True, transform=transforms.ToTensor(),download=True)
test_dataset = torchvision.datasets.MNIST(root='../../data/',train=False, transform=transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size, shuffle=True)test_loader = torch.utils.data.DataLoader(dataset=test_dataset,batch_size=batch_size, shuffle=False)
class ConvNet(nn.Module):def __init__(self, num_classes=10):super(ConvNet, self).__init__()self.layer1 = nn.Sequential(nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(16),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2))self.layer2 = nn.Sequential(nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(32),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2))self.fc = nn.Linear(7*7*32, num_classes)def forward(self, x):out = self.layer1(x)out = self.layer2(out)out = out.reshape(out.size(0), -1)out = self.fc(out)return outmodel = ConvNet(num_classes).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
total_step = len(train_loader)
for epoch in range(num_epochs):for i, (images, labels) in enumerate(train_loader):images = images.to(device)labels = labels.to(device)outputs = model(images)loss = criterion(outputs, labels)optimizer.zero_grad()loss.backward()optimizer.step()if (i+1) % 100 == 0:print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' .format(epoch+1, num_epochs, i+1, total_step, loss.item()))
model.eval()
with torch.no_grad():correct = 0total = 0for images, labels in test_loader:images = images.to(device)labels = labels.to(device)outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))
torch.save(model.state_dict(), 'model.ckpt')
我们根据训练的结果可以看到比全连接层训练的结果准确率高。
补充
在卷积层是否需要padding ?根据输入图像边缘携带信息特征是否足以影响分类的准确性来决定 。降采样的作用是一种典型的降维操作,可以使用最大池化和平均池化。表现了一种以一定的信息损失为代价来换取空间和运算时间的取舍态度。
关于是用最大池化和平均池化根据自己对输出的要求。卷积层可以在任何网络结构中出现,是作为特征提取,池化层的作用是降维。降低模型的训练难度。
关于卷积核的数量,有几个通道的输出,就定义多少个卷积核。
多卷积核
上面只有100个参数的时候,表明只有1个10*10的卷积核,显然特征提取是不充分的,可以添加n个卷积核,可以学习n种特征。
RNN神经网络
循环神经网络最流行的就是LSTM,RNN与FF和CNN是不同的,FF是全连接层实现,CNN是卷积层实现,LSTM是用循环层实现的,就是把前一次输入的内容以及中间的激励值和这一次的输入值一起作为网络的输入,这样如果上一次的输入对这一次的输入有影响,那么这种影响也可以被学习,特别是对于文本处理的时候,根据上下文来推断这个词语的意思,用LSTM是很好的。