卷积神经网络(Convolutional Neural Network)
绪论
1.卷积神经网络应用
- 分类
- 检索
- 人脸识别
- 表情识别
- 检测
- 人脸验证
- 分割(有点像抠图)
- 自动驾驶
2.传统神经网络vs卷积神经网络
深度学习三部曲
step1. 搭建神经网络结构
step2. 找到一个合适的损失函数
损失函数是衡量吻合度的,可以调整参数/权重W,使得映射的结果和实际类别吻合
传统神经网络也可以应用到计算机视觉,但是会有如下问题:参数太多,会造成过拟合(泛化性能差)
卷积神经网络:局部关联,参数共享
step3. 找到一个合适的优化函数,更新参数
相同之处:分层:卷积层,激活层,池化层,全连接层
基本组成结构
卷积:卷积是对两个实变函数的一种数学操作 实变函数:以实数为自变量的函数
二维卷积
一维卷积:常用在信号处理中,用于计算信号的延迟累计
滤波器(filter)
卷积核:信息的衰减率
基本概念:
- 输入
- 卷积核/滤波器
- 权重
- 感受野(receptive field)
- 特征图(feature map)
- padding(输入的两边补0)
- 深度(channel)
- 输出(output)
- 步长(stride)
池化:(pooling layer):保留了主要特征的同时减少参数和计算量,防止过拟合,提高模型泛化的能力。它一般处于卷积层与卷积层之间,全连接层与全连接层之间。
- 最大值池化
- 平均值池化
全连接:(FC layer)两层之间的所有神经元都有权重链接,通常全连接层在卷积神经网络的尾部,全连接层参数量通常最大
小结:
- 一个典型的卷积神经网络是由卷积层、池化层交叉堆叠而成,最后一层是全连接层
卷积神经网络典型结构
AlexNet
非线性激活函数:ReLU函数:优点:
- 解决了梯度消失问题
- 计算速度特别快,只需要判断输入是否大于0
- 收敛速度远快于sigmoid
AlexNet分层解析
ZFNet
网络结构与AlexNet相同
VGG
VGG是一个更深网络 8->16
GoogleNet
- 网络包含22个带参数的层,独立成块的层总共有100个
- 参数量大概是Alexnet的1/12
- 没有FC层
inception模块 用小的卷积核替代大的卷积核
ResNet(残差学习网络)
代码练习
MNIST 数据集分类
-
加载数据(MINIST)
-
创建网络
-
在小型全连接网络上训练(Fully-connected network)
- 在卷积神经网络上训练
# Training settings
n_features = 6 # number of feature maps
model_cnn = CNN(input_size, n_features, output_size)
model_cnn.to(device)
optimizer = optim.SGD(model_cnn.parameters(), lr=0.01, momentum=0.5)
print('Number of parameters: {}'.format(get_n_params(model_cnn)))
train(model_cnn)
test(model_cnn)
通过上面的测试结果,可以发现,含有相同参数的 CNN 效果要明显优于 简单的全连接网络,是因为 CNN 能够更好的挖掘图像中的信息,主要通过两个手段:
- 卷积:Locality and stationarity in images
- 池化:Builds in some translation invariance
-
打乱像素顺序再次在两个网络上训练与测试
-
在全连接网络上训练与测试
Number of parameters: 6442 Train: [0/60000 (0%)] Loss: 2.264858 Train: [6400/60000 (11%)] Loss: 2.041490 Train: [12800/60000 (21%)] Loss: 1.552290 Train: [19200/60000 (32%)] Loss: 1.093537 Train: [25600/60000 (43%)] Loss: 0.799383 Train: [32000/60000 (53%)] Loss: 0.847221 Train: [38400/60000 (64%)] Loss: 0.756004 Train: [44800/60000 (75%)] Loss: 0.723714 Train: [51200/60000 (85%)] Loss: 0.438829 Train: [57600/60000 (96%)] Loss: 0.474032 Test set: Average loss: 0.5751, Accuracy: 8348/10000 (83%)
-
在卷积神经网络上训练与测试:
Number of parameters: 6422 Train: [0/60000 (0%)] Loss: 2.300903 Train: [6400/60000 (11%)] Loss: 2.282535 Train: [12800/60000 (21%)] Loss: 2.261807 Train: [19200/60000 (32%)] Loss: 2.111837 Train: [25600/60000 (43%)] Loss: 1.717916 Train: [32000/60000 (53%)] Loss: 1.320999 Train: [38400/60000 (64%)] Loss: 0.960259 Train: [44800/60000 (75%)] Loss: 0.961738 Train: [51200/60000 (85%)] Loss: 0.636504 Train: [57600/60000 (96%)] Loss: 0.507474 Test set: Average loss: 0.6227, Accuracy: 8003/10000 (80%)
从打乱像素顺序的实验结果来看,全连接网络的性能基本上没有发生变化,但是 卷积神经网络的性能明显下降。
这是因为对于卷积神经网络,会利用像素的局部关系,但是打乱顺序以后,这些像素间的关系将无法得到利用。
-
CIFAR10 数据集分类
接下来定义网络,损失函数和优化器:
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
# 网络放到GPU上
net = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
训练网络:
for epoch in range(10): # 重复多轮训练
for i, (inputs, labels) in enumerate(trainloader):
inputs = inputs.to(device)
labels = labels.to(device)
# 优化器梯度归零
optimizer.zero_grad()
# 正向传播 + 反向传播 + 优化
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 输出统计信息
if i % 100 == 0:
print('Epoch: %d Minibatch: %5d loss: %.3f' %(epoch + 1, i + 1, loss.item()))
print('Finished Training')
网络在整个数据集上的表现:
Accuracy of the network on the 10000 test images: 62 %
使用 VGG16 对 CIFAR10 分类,链接:
VGG是由Simonyan 和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型,其名称来源于作者所在的牛津大学视觉几何组(Visual Geometry Group)的缩写。
该模型参加2014年的 ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。
VGG16的网络结构如下图所示:
-
定义dataloader
需要注意的是,这里的 transform,dataloader 和之前定义的有所不同
-
定义VGG网络
-
网络训练
训练结果
correct = 0 total = 0 for data in testloader: images, labels = data images, labels = images.to(device), labels.to(device) 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: %.2f %%' % ( 100 * correct / total))
Accuracy of the network on the 10000 test images: 84.92 %
可以看到,使用一个简化版的 VGG 网络,就能够显著地将准确率由 64%,提升到 84.92%
思考
-
dataloader 里面 shuffle 取不同值有什么区别?
Dataloader中设置了shuffle是True,所以每次加载的数据都是随机的。
洗牌。默认设置为False。在每次迭代训练时是否将数据洗牌,默认设置是False。将输入数据的顺序打乱,是为了使数据更有独立 性,但如果数据是有序列特征的,就不要设置成True了
-
transform 里,取了不同值,这个有什么区别?
transform的作用:对图像进行一定的预处理,相当于扩展数据集。
transform的处理方法
1 裁剪-Crop
2 翻转和旋转——Flip and Rotation
3 图像变换
4 对transforms操作,使数据增强更灵活
-
epoch 和 batch 的区别?
epoch:当一个完整的数据集经过神经网络一次,并返回一次,这个过程称为一个epoch。
batch:当数据集很大的时候,对于每个epoch,很难将所有的数据集一次读入到内存中,这是需要将数据集分为几次读入,每次称为一个batch。
-
1x1的卷积和 FC 有什么区别?主要起什么作用?
1*1的卷积:
- 添加非线性特性
即保持特征图尺寸不发生变化且维持上一层的通道数,在增加网络的深度的同时令网络能够学习更为复杂的函数(特征信息)。
- 对通道数实现升维降维:一般用降维来减少计算量
FC(全连接层):起到分类器的作用。对前层的特征进行一个加权和,(卷积层是将数据输入映射到隐层特征空间)将特征空间通过线性变换映射到样本标记空间(也就是label)
区别:
全连接是把特征图拆开组成一个一维向量,再乘以一个权重向量,这两个向量中的元素一一对应所以输出结果是一个值。
11的卷积核那就是表明只由一个权重组成,如果特征图尺寸也是11的话,那输出就是一个值,此时与全连接完全一样。但是如果特征图尺寸不是11,而是wh的话,那么11的卷积输出就不是一个值而是wh的一个矩阵。
用11卷积代替全连接应该是基于输入尺寸的考虑,全连接的输入是特征图所有元素乘以权重再求和,但是这个权重向量是在设计网络的时候就需要固定的,所以全连接没办法适应输入尺寸的变化只能固定。但是11卷积的输出与输入尺寸是一样大的,输出尺寸可以随着输入尺寸的变化而变化,所以1*1卷积无需固定输出尺寸。
-
residual leanring 为什么能够提升准确率?
残差的思想都是去掉相同的主体部分,从而突出微小的变化,引入残差后的映射对输出的变化更敏感。很明显,在残差网络中输出的变化对权重的调整影响更大,也就是说反向传播的梯度值更大,训练就更加容易。
-
代码练习二里,网络和1989年 Lecun 提出的 LeNet 有什么区别?
- LeNet :最早用于手写数字识别的CNN网络
-
有什么方法可以进一步提升准确率?
-
增加更多数据
-
2.处理缺失值和异常值
-
特征工程学:这一步骤有助于从现有数据中提取更多信息。新信息作为新特征被提取出来。这些特征可能会更好地解释训练集中的差异变化。因此能改善模型的准确率。
-
特征选择:特征选择是寻找众多属性的哪个子集合,能够最好的解释目标变量与各个自变量的关系的过程。
你可以根据多种标准选取有用的特征
-
使用多种算法
-
交叉验证:如果想解决这个问题,我们必须使用交叉验证技术(cross validation)。交叉验证是数据建模领域最重要的概念之一。它是指,保留一部分数据样本不用来训练模型,而是在完成模型前用来验证。
-