卷积神经网络 - 垃圾分类
代码和数据集可以在 我的AI学习笔记 - github 中获取
实验内容
自今年7月1日起,上海市将正式实施 《上海市生活垃圾管理条例》。垃圾分类,看似是微不足道的“小事”,实则关系到13亿多人生活环境的改善,理应大力提倡。
垃圾识别分类数据集中包括 glass、cardboard、metal、paper、plastic、trash,共6个类别。
生活垃圾由于种类繁多,具体分类缺乏统一标准,大多人在实际操作时会“选择困难”,基于深度学习技术建立准确的分类模型,利用技术手段改善人居环境。
数据集
该数据集包含了 2307 个生活垃圾图片。数据集的创建者将垃圾分为了 6 个类别,分别是:
序号 | 中文名 | 英文名 | 数据集大小 |
---|---|---|---|
1 | 玻璃 | glass | 457 |
2 | 纸 | paper | 540 |
3 | 硬纸板 | cardboard | 370 |
4 | 塑料 | plastic | 445 |
5 | 金属 | metal | 380 |
6 | 一般垃圾 | trash | 115 |
物品都是放在白板上在日光/室内光源下拍摄的,压缩后的尺寸为 512 * 384.
实验要求
-
建立深度学习模型,并尽可能将其调到最佳状态
-
绘制深度学习模型图、绘制并分析学习曲线等
-
分析模型并试着调试不同学习率等超参数对模型的结果影响
本地环境:
GPU:
- NVIDIA Quadro P600
- 驱动程序版本:442.92
- CUDA:10.1(已添加到系统环境变量)
torch 1.5.0+cu101
torchvision 0.6.0+cu101
安装使用均没有报错,并可以使用GPU进行训练。
记录
DNN;开始给的示例代码模型, 一个简单的全连接神经网络
inputs = Input(shape=input_shape)
# 将输入展平
dnn = Flatten()(inputs)
# Dense 全连接层
dnn = Dense(6)(dnn)
dnn = BatchNormalization(axis=-1)(dnn)
dnn = Activation('sigmoid')(dnn)
dnn = Dropout(0.25)(dnn)
dnn = Dense(12)(dnn)
dnn = BatchNormalization(axis=-1)(dnn)
dnn = Activation('relu')(dnn)
dnn = Dropout(0.5)(dnn)
dnn = Dense(6)(dnn)
dnn = BatchNormalization(axis=-1)(dnn)
dnn = Activation('softmax')(dnn)
outputs = dnn
# 生成一个函数型模型
model = Model(inputs=inputs, outputs=outputs)
训练要好一会儿,模型正确率大概在0.3左右;
尝试了一个简单的卷积神经网络模型
随便找的
model = Sequential()
model.add(Conv2D(32, (5, 5), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(32, (5, 5), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Flatten())
model.add(Dense(12, activation='relu'))
model.add(Dense(6))
model.add(BatchNormalization(axis=-1))
model.add(Activation('softmax'))
训练正确率大约在0.5 - 0.6,但发生了过拟合,在比赛数据集中只有30%的识别准确率。训练参数和示例一样(没改)
pytorch调参学习
由于是初次接触pytorch和除了samples以外实际上手调参,还是比较茫然的…
尝试过了从头训练神经网络和迁移学习两种方式;
resnet
def getRsn():
model = models.resnet18(pretrained=True)
num_fc_in = model.fc.in_features
model.fc = nn.Linear(num_fc_in, 6)
return model
MO上似乎加载resnet的话内存有可能会出现超限的问题(是不是我哪里操作不正确
mobilenet_v2
于是就尝试了一下mobilenet_v2,但可能由于过拟合的原因,实际在测试数据上表现并不好;
可以再尝试尝试;
def getMbnet():
model = models.mobilenet_v2(pretrained=True)
model.classifier = nn.Sequential(
nn.Linear(in_features=1280,out_features=64),
nn.Dropout(p=0.5,inplace=False),
nn.Linear(in_features=64,out_features=6,bias=True),
)
return model
自己写的一个简单的CNN
大致就是普通CNN的结构,先多层卷积层池化层,然后用全连接层解决分类问题;
class MyCNN(nn.Module):
"""
网络模型
"""
def __init__(self, image_size, num_classes):
super(MyCNN, self).__init__()
# conv1: Conv2d -> BN -> ReLU -> MaxPool
self.conv1 = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels=16, out_channels=16, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=1),
)
# conv2: Conv2d -> BN -> ReLU -> MaxPool
self.conv2 = nn.Sequential(
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1