https://aistudio.baidu.com/aistudio/course/introduce/11939?directly=1&shared=1先附上飞桨的课程链接,大家可以去学习
如何根据据图像的视觉内容为图像赋予一个语义类别是图像分类的目标,也是图像检索、图像内容分析和目标识别等问题的基础。
本实践旨在通过一个美食分类的案列,让大家理解和掌握如何使用飞桨2.0搭建一个卷积神经网络。
特别提示:本实践所用数据集均来自互联网,请勿用于商务用途。
解压文件,使用train.csv训练,测试使用val.csv。最后以在val上的准确率作为最终分数。
思考并动手进行调优,以在验证集上的准确率为评价指标,验证集上准确率越高,得分越高!模型大家可以更换,调参技巧任选,代码需要大家自己调通。
# 解压相关数据
!cd data/data72793/ && unzip -q lemon_homework.zip
!cd data/data72793/lemon_homework/ && unzip -q lemon_lesson.zip
!cd data/data72793/lemon_homework/lemon_lesson/ && unzip -q test_images.zip
!cd data/data72793/lemon_homework/lemon_lesson/ && unzip -q train_images.zip
# 导入所需要的库
from sklearn.utils import shuffle
import os
import pandas as pd
import numpy as np
from PIL import Image
import paddle
import paddle.nn as nn
from paddle.io import Dataset
import paddle.vision.transforms as T
import paddle.nn.functional as F
from paddle.metric import Accuracy
import warnings
warnings.filterwarnings("ignore")
# 读取数据
train_images = pd.read_csv('data/data72793/lemon_homework/lemon_lesson/train_images.csv', usecols=['id','class_num'])
# labelshuffling 用于打乱数据
def labelShuffling(dataFrame, groupByName = 'class_num'):
groupDataFrame = dataFrame.groupby(by=[groupByName])
labels = groupDataFrame.size()
print("length of label is ", len(labels))
maxNum = max(labels)
lst = pd.DataFrame()
for i in range(len(labels)):
print("Processing label :", i)
tmpGroupBy = groupDataFrame.get_group(i)
createdShuffleLabels = np.random.permutation(np.array(range(maxNum))) % labels[i]
print("Num of the label is : ", labels[i])
lst=lst.append(tmpGroupBy.iloc[createdShuffleLabels], ignore_index=True)
print("Done")
# lst.to_csv('test1.csv', index=False)
return lst
# 划分训练集和校验集
all_size = len(train_images)
# print(all_size)
train_size = int(all_size * 0.8)
train_image_list = train_images[:train_size]
val_image_list = train_images[train_size:]
df = labelShuffling(train_image_list)
df = shuffle(df)
train_image_path_list = df['id'].values
label_list = df['class_num'].values
label_list = paddle.to_tensor(label_list, dtype='int64')
train_label_list = paddle.nn.functional.one_hot(label_list, num_classes=4)
val_image_path_list = val_image_list['id'].values
val_label_list = val_image_list['class_num'].values
val_label_list = paddle.to_tensor(val_label_list, dtype='int64')
val_label_list = paddle.nn.functional.one_hot(val_label_list, num_classes=4)
# 定义数据预处理
# 这里采用了部分数据增强的高阶API,详见paddle文档
data_transforms = T.Compose([
T.Resize(size=(224, 224)),# 注意图像size
T.RandomHorizontalFlip(224),
T.RandomVerticalFlip(224),
T.ColorJitter(0.4,0.4,0.4,0.4),
T.RandomRotation(90),
T.Transpose(), # HWC -> CHW
T.Normalize(
mean=[0, 0, 0], # 归一化
std=[255, 255, 255],
to_rgb=True)
])
length of label is 4
Processing label : 0
Num of the label is : 321
Done
Processing label : 1
Num of the label is : 207
Done
Processing label : 2
Num of the label is : 181
Done
Processing label : 3
Num of the label is : 172
Done
# 构建Dataset
class MyDataset(paddle.io.Dataset):
"""
步骤一:继承paddle.io.Dataset类
"""
def __init__(self, train_img_list, val_img_list,train_label_list,val_label_list, mode='train'):
"""
步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集
"""
super(MyDataset, self).__init__()
self.img = []
self.label = []
# 借助pandas读csv的库
self.train_images = train_img_list
self.test_images = val_img_list
self.train_label = train_label_list
self.test_label = val_label_list
if mode == 'train':
# 读train_images的数据
for img,la in zip(self.train_images, self.train_label):
self.img.append('data/data72793/lemon_homework/lemon_lesson/train_images/'+img)
self.label.append(la)
else:
# 读test_images的数据
for img,la in zip(self.test_images, self.test_label):
self.img.append('data/data72793/lemon_homework/lemon_lesson/train_images/'+img)
self.label.append(la)
def load_img(self, image_path):
# 实际使用时使用Pillow相关库进行图片读取即可,这里我们对数据先做个模拟
image = Image.open(image_path).convert('RGB')
return image
def __getitem__(self, index):
"""
步骤三:实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据(训练数据,对应的标签)
"""
image = self.load_img(self.img[index])
label = self.label[index]
# label = paddle.to_tensor(label)
# 注意数据类型,不然可能会报错
return data_transforms(image).astype("float32"), paddle.nn.functional.label_smooth(label)
def __len__(self):
"""
步骤四:实现__len__方法,返回数据集总数目
"""
return len(self.img)
#train_loader
train_dataset = MyDataset(train_img_list=train_image_path_list, val_img_list=val_image_path_list,
train_label_list=train_label_list, val_label_list=val_label_list, mode='train')
train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), batch_size=32, shuffle=True, num_workers=0)
#val_loader
val_dataset = MyDataset(train_img_list=train_image_path_list, val_img_list=val_image_path_list,
train_label_list=train_label_list, val_label_list=val_label_list, mode='test')
val_loader = paddle.io.DataLoader(val_dataset, places=paddle.CPUPlace(), batch_size=32, shuffle=True, num_workers=0)
# print('=============train dataset=============')
# for image, label in train_dataset:
# print('image shape: {}, label: {}'.format(image.shape, label))
# break
# print('=============evaluation dataset=============')
# for image, label in val_dataset:
# print('image shape: {}, label: {}'.format(image.shape, label))
# break
print(val_dataset[1][0].shape)
print(train_dataset[1][1])
print(train_dataset[0][0])
(3, 224, 224)
Tensor(shape=[4], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
[0.92499995, 0.02500000, 0.02500000, 0.02500000])
[[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]]
from paddle.vision import MobileNetV2
paddle.set_device('gpu:0')
# 模型封装
model_res = MobileNetV2(num_classes=4)
model = paddle.Model(model_res)
# 定义优化器
# 这里没有采用的是普通的恒定学习速度,可根据自己需要进行更改
scheduler = paddle.optimizer.lr.LinearWarmup(
learning_rate=0.5, warmup_steps=20, start_lr=0, end_lr=0.5, verbose=True)
# optim = paddle.optimizer.SGD(learning_rate=scheduler, parameters=model.parameters())
optim = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
# 配置模型
model.prepare(
optim,
paddle.nn.CrossEntropyLoss(soft_label=True),
Accuracy()
)
# 模型训练与评估
model.fit(train_loader,
# val_loader,
log_freq=1,
epochs=20,
# 支持自定义的callbacks,详见paddle文档
# callbacks=Callbk(write=write, iters=iters),
verbose=1,
)
Epoch 0: LinearWarmup set learning rate to 0.0.
The loss value printed in the log is the current step, and the metric is the average value of previous step.
Epoch 1/20
step 41/41 [==============================] - loss: 1.3569 - acc: 0.3053 - 493ms/step
Epoch 2/20
step 41/41 [==============================] - loss: 1.1020 - acc: 0.4011 - 496ms/step
Epoch 3/20
step 41/41 [==============================] - loss: 0.9861 - acc: 0.5763 - 498ms/step
Epoch 4/20
step 41/41 [==============================] - loss: 2.1510 - acc: 0.6285 - 504ms/step
Epoch 5/20
step 41/41 [==============================] - loss: 1.7331 - acc: 0.7204 - 491ms/step
Epoch 6/20
step 41/41 [==============================] - loss: 0.6863 - acc: 0.7702 - 495ms/step
Epoch 7/20
step 41/41 [==============================] - loss: 0.4440 - acc: 0.7913 - 492ms/step
Epoch 8/20
step 41/41 [==============================] - loss: 0.5644 - acc: 0.8333 - 508ms/step
Epoch 9/20
step 41/41 [==============================] - loss: 0.4993 - acc: 0.8738 - 540ms/step
Epoch 10/20
step 41/41 [==============================] - loss: 0.9950 - acc: 0.8567 - 510ms/step
Epoch 11/20
step 41/41 [==============================] - loss: 0.6244 - acc: 0.8512 - 522ms/step
Epoch 12/20
step 41/41 [==============================] - loss: 1.0610 - acc: 0.8785 - 526ms/step
Epoch 13/20
step 41/41 [==============================] - loss: 0.5871 - acc: 0.8816 - 524ms/step
Epoch 14/20
step 41/41 [==============================] - loss: 0.5231 - acc: 0.8956 - 530ms/step
Epoch 15/20
step 41/41 [==============================] - loss: 1.0331 - acc: 0.9019 - 495ms/step
Epoch 16/20
step 41/41 [==============================] - loss: 0.6407 - acc: 0.8863 - 498ms/step
Epoch 17/20
step 41/41 [==============================] - loss: 1.0146 - acc: 0.9042 - 514ms/step
Epoch 18/20
step 41/41 [==============================] - loss: 1.1974 - acc: 0.9003 - 497ms/step
Epoch 19/20
step 41/41 [==============================] - loss: 1.4053 - acc: 0.8863 - 495ms/step
Epoch 20/20
step 41/41 [==============================] - loss: 0.4991 - acc: 0.9003 - 493ms/step
# 查看网络
model.summary((1, 3, 224, 224))
--------------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
================================================================================
Conv2D-365 [[1, 3, 224, 224]] [1, 32, 112, 112] 864
BatchNorm2D-365 [[1, 32, 112, 112]] [1, 32, 112, 112] 128
ReLU6-246 [[1, 32, 112, 112]] [1, 32, 112, 112] 0
Conv2D-366 [[1, 32, 112, 112]] [1, 32, 112, 112] 288
BatchNorm2D-366 [[1, 32, 112, 112]] [1, 32, 112, 112] 128
ReLU6-247 [[1, 32, 112, 112]] [1, 32, 112, 112] 0
Conv2D-367 [[1, 32, 112, 112]] [1, 16, 112, 112] 512
BatchNorm2D-367 [[1, 16, 112, 112]] [1, 16, 112, 112] 64
InvertedResidual-120 [[1, 32, 112, 112]] [1, 16, 112, 112] 0
Conv2D-368 [[1, 16, 112, 112]] [1, 96, 112, 112] 1,536
BatchNorm2D-368 [[1, 96, 112, 112]] [1, 96, 112, 112] 384
ReLU6-248 [[1, 96, 112, 112]] [1, 96, 112, 112] 0
Conv2D-369 [[1, 96, 112, 112]] [1, 96, 56, 56] 864
BatchNorm2D-369 [[1, 96, 56, 56]] [1, 96, 56, 56] 384
ReLU6-249 [[1, 96, 56, 56]] [1, 96, 56, 56] 0
Conv2D-370 [[1, 96, 56, 56]] [1, 24, 56, 56] 2,304
BatchNorm2D-370 [[1, 24, 56, 56]] [1, 24, 56, 56] 96
InvertedResidual-121 [[1, 16, 112, 112]] [1, 24, 56, 56] 0
Conv2D-371 [[1, 24, 56, 56]] [1, 144, 56, 56] 3,456
BatchNorm2D-371 [[1, 144, 56, 56]] [1, 144, 56, 56] 576
ReLU6-250 [[1, 144, 56, 56]] [1, 144, 56, 56] 0
Conv2D-372 [[1, 144, 56, 56]] [1, 144, 56, 56] 1,296
BatchNorm2D-372 [[1, 144, 56, 56]] [1, 144, 56, 56] 576
ReLU6-251 [[1, 144, 56, 56]] [1, 144, 56, 56] 0
Conv2D-373 [[1, 144, 56, 56]] [1, 24, 56, 56] 3,456
BatchNorm2D-373 [[1, 24, 56, 56]] [1, 24, 56, 56] 96
InvertedResidual-122 [[1, 24, 56, 56]] [1, 24, 56, 56] 0
Conv2D-374 [[1, 24, 56, 56]] [1, 144, 56, 56] 3,456
BatchNorm2D-374 [[1, 144, 56, 56]] [1, 144, 56, 56] 576
ReLU6-252 [[1, 144, 56, 56]] [1, 144, 56, 56] 0
Conv2D-375 [[1, 144, 56, 56]] [1, 144, 28, 28] 1,296
BatchNorm2D-375 [[1, 144, 28, 28]] [1, 144, 28, 28] 576
ReLU6-253 [[1, 144, 28, 28]] [1, 144, 28, 28] 0
Conv2D-376 [[1, 144, 28, 28]] [1, 32, 28, 28] 4,608
BatchNorm2D-376 [[1, 32, 28, 28]] [1, 32, 28, 28] 128
InvertedResidual-123 [[1, 24, 56, 56]] [1, 32, 28, 28] 0
Conv2D-377 [[1, 32, 28, 28]] [1, 192, 28, 28] 6,144
BatchNorm2D-377 [[1, 192, 28, 28]] [1, 192, 28, 28] 768
ReLU6-254 [[1, 192, 28, 28]] [1, 192, 28, 28] 0
Conv2D-378 [[1, 192, 28, 28]] [1, 192, 28, 28] 1,728
BatchNorm2D-378 [[1, 192, 28, 28]] [1, 192, 28, 28] 768
ReLU6-255 [[1, 192, 28, 28]] [1, 192, 28, 28] 0
Conv2D-379 [[1, 192, 28, 28]] [1, 32, 28, 28] 6,144
BatchNorm2D-379 [[1, 32, 28, 28]] [1, 32, 28, 28] 128
InvertedResidual-124 [[1, 32, 28, 28]] [1, 32, 28, 28] 0
Conv2D-380 [[1, 32, 28, 28]] [1, 192, 28, 28] 6,144
BatchNorm2D-380 [[1, 192, 28, 28]] [1, 192, 28, 28] 768
ReLU6-256 [[1, 192, 28, 28]] [1, 192, 28, 28] 0
Conv2D-381 [[1, 192, 28, 28]] [1, 192, 28, 28] 1,728
BatchNorm2D-381 [[1, 192, 28, 28]] [1, 192, 28, 28] 768
ReLU6-257 [[1, 192, 28, 28]] [1, 192, 28, 28] 0
Conv2D-382 [[1, 192, 28, 28]] [1, 32, 28, 28] 6,144
BatchNorm2D-382 [[1, 32, 28, 28]] [1, 32, 28, 28] 128
InvertedResidual-125 [[1, 32, 28, 28]] [1, 32, 28, 28] 0
Conv2D-383 [[1, 32, 28, 28]] [1, 192, 28, 28] 6,144
BatchNorm2D-383 [[1, 192, 28, 28]] [1, 192, 28, 28] 768
ReLU6-258 [[1, 192, 28, 28]] [1, 192, 28, 28] 0
Conv2D-384 [[1, 192, 28, 28]] [1, 192, 14, 14] 1,728
BatchNorm2D-384 [[1, 192, 14, 14]] [1, 192, 14, 14] 768
ReLU6-259 [[1, 192, 14, 14]] [1, 192, 14, 14] 0
Conv2D-385 [[1, 192, 14, 14]] [1, 64, 14, 14] 12,288
BatchNorm2D-385 [[1, 64, 14, 14]] [1, 64, 14, 14] 256
InvertedResidual-126 [[1, 32, 28, 28]] [1, 64, 14, 14] 0
Conv2D-386 [[1, 64, 14, 14]] [1, 384, 14, 14] 24,576
BatchNorm2D-386 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-260 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-387 [[1, 384, 14, 14]] [1, 384, 14, 14] 3,456
BatchNorm2D-387 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-261 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-388 [[1, 384, 14, 14]] [1, 64, 14, 14] 24,576
BatchNorm2D-388 [[1, 64, 14, 14]] [1, 64, 14, 14] 256
InvertedResidual-127 [[1, 64, 14, 14]] [1, 64, 14, 14] 0
Conv2D-389 [[1, 64, 14, 14]] [1, 384, 14, 14] 24,576
BatchNorm2D-389 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-262 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-390 [[1, 384, 14, 14]] [1, 384, 14, 14] 3,456
BatchNorm2D-390 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-263 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-391 [[1, 384, 14, 14]] [1, 64, 14, 14] 24,576
BatchNorm2D-391 [[1, 64, 14, 14]] [1, 64, 14, 14] 256
InvertedResidual-128 [[1, 64, 14, 14]] [1, 64, 14, 14] 0
Conv2D-392 [[1, 64, 14, 14]] [1, 384, 14, 14] 24,576
BatchNorm2D-392 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-264 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-393 [[1, 384, 14, 14]] [1, 384, 14, 14] 3,456
BatchNorm2D-393 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-265 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-394 [[1, 384, 14, 14]] [1, 64, 14, 14] 24,576
BatchNorm2D-394 [[1, 64, 14, 14]] [1, 64, 14, 14] 256
InvertedResidual-129 [[1, 64, 14, 14]] [1, 64, 14, 14] 0
Conv2D-395 [[1, 64, 14, 14]] [1, 384, 14, 14] 24,576
BatchNorm2D-395 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-266 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-396 [[1, 384, 14, 14]] [1, 384, 14, 14] 3,456
BatchNorm2D-396 [[1, 384, 14, 14]] [1, 384, 14, 14] 1,536
ReLU6-267 [[1, 384, 14, 14]] [1, 384, 14, 14] 0
Conv2D-397 [[1, 384, 14, 14]] [1, 96, 14, 14] 36,864
BatchNorm2D-397 [[1, 96, 14, 14]] [1, 96, 14, 14] 384
InvertedResidual-130 [[1, 64, 14, 14]] [1, 96, 14, 14] 0
Conv2D-398 [[1, 96, 14, 14]] [1, 576, 14, 14] 55,296
BatchNorm2D-398 [[1, 576, 14, 14]] [1, 576, 14, 14] 2,304
ReLU6-268 [[1, 576, 14, 14]] [1, 576, 14, 14] 0
Conv2D-399 [[1, 576, 14, 14]] [1, 576, 14, 14] 5,184
BatchNorm2D-399 [[1, 576, 14, 14]] [1, 576, 14, 14] 2,304
ReLU6-269 [[1, 576, 14, 14]] [1, 576, 14, 14] 0
Conv2D-400 [[1, 576, 14, 14]] [1, 96, 14, 14] 55,296
BatchNorm2D-400 [[1, 96, 14, 14]] [1, 96, 14, 14] 384
InvertedResidual-131 [[1, 96, 14, 14]] [1, 96, 14, 14] 0
Conv2D-401 [[1, 96, 14, 14]] [1, 576, 14, 14] 55,296
BatchNorm2D-401 [[1, 576, 14, 14]] [1, 576, 14, 14] 2,304
ReLU6-270 [[1, 576, 14, 14]] [1, 576, 14, 14] 0
Conv2D-402 [[1, 576, 14, 14]] [1, 576, 14, 14] 5,184
BatchNorm2D-402 [[1, 576, 14, 14]] [1, 576, 14, 14] 2,304
ReLU6-271 [[1, 576, 14, 14]] [1, 576, 14, 14] 0
Conv2D-403 [[1, 576, 14, 14]] [1, 96, 14, 14] 55,296
BatchNorm2D-403 [[1, 96, 14, 14]] [1, 96, 14, 14] 384
InvertedResidual-132 [[1, 96, 14, 14]] [1, 96, 14, 14] 0
Conv2D-404 [[1, 96, 14, 14]] [1, 576, 14, 14] 55,296
BatchNorm2D-404 [[1, 576, 14, 14]] [1, 576, 14, 14] 2,304
ReLU6-272 [[1, 576, 14, 14]] [1, 576, 14, 14] 0
Conv2D-405 [[1, 576, 14, 14]] [1, 576, 7, 7] 5,184
BatchNorm2D-405 [[1, 576, 7, 7]] [1, 576, 7, 7] 2,304
ReLU6-273 [[1, 576, 7, 7]] [1, 576, 7, 7] 0
Conv2D-406 [[1, 576, 7, 7]] [1, 160, 7, 7] 92,160
BatchNorm2D-406 [[1, 160, 7, 7]] [1, 160, 7, 7] 640
InvertedResidual-133 [[1, 96, 14, 14]] [1, 160, 7, 7] 0
Conv2D-407 [[1, 160, 7, 7]] [1, 960, 7, 7] 153,600
BatchNorm2D-407 [[1, 960, 7, 7]] [1, 960, 7, 7] 3,840
ReLU6-274 [[1, 960, 7, 7]] [1, 960, 7, 7] 0
Conv2D-408 [[1, 960, 7, 7]] [1, 960, 7, 7] 8,640
BatchNorm2D-408 [[1, 960, 7, 7]] [1, 960, 7, 7] 3,840
ReLU6-275 [[1, 960, 7, 7]] [1, 960, 7, 7] 0
Conv2D-409 [[1, 960, 7, 7]] [1, 160, 7, 7] 153,600
BatchNorm2D-409 [[1, 160, 7, 7]] [1, 160, 7, 7] 640
InvertedResidual-134 [[1, 160, 7, 7]] [1, 160, 7, 7] 0
Conv2D-410 [[1, 160, 7, 7]] [1, 960, 7, 7] 153,600
BatchNorm2D-410 [[1, 960, 7, 7]] [1, 960, 7, 7] 3,840
ReLU6-276 [[1, 960, 7, 7]] [1, 960, 7, 7] 0
Conv2D-411 [[1, 960, 7, 7]] [1, 960, 7, 7] 8,640
BatchNorm2D-411 [[1, 960, 7, 7]] [1, 960, 7, 7] 3,840
ReLU6-277 [[1, 960, 7, 7]] [1, 960, 7, 7] 0
Conv2D-412 [[1, 960, 7, 7]] [1, 160, 7, 7] 153,600
BatchNorm2D-412 [[1, 160, 7, 7]] [1, 160, 7, 7] 640
InvertedResidual-135 [[1, 160, 7, 7]] [1, 160, 7, 7] 0
Conv2D-413 [[1, 160, 7, 7]] [1, 960, 7, 7] 153,600
BatchNorm2D-413 [[1, 960, 7, 7]] [1, 960, 7, 7] 3,840
ReLU6-278 [[1, 960, 7, 7]] [1, 960, 7, 7] 0
Conv2D-414 [[1, 960, 7, 7]] [1, 960, 7, 7] 8,640
BatchNorm2D-414 [[1, 960, 7, 7]] [1, 960, 7, 7] 3,840
ReLU6-279 [[1, 960, 7, 7]] [1, 960, 7, 7] 0
Conv2D-415 [[1, 960, 7, 7]] [1, 320, 7, 7] 307,200
BatchNorm2D-415 [[1, 320, 7, 7]] [1, 320, 7, 7] 1,280
InvertedResidual-136 [[1, 160, 7, 7]] [1, 320, 7, 7] 0
Conv2D-416 [[1, 320, 7, 7]] [1, 1280, 7, 7] 409,600
BatchNorm2D-416 [[1, 1280, 7, 7]] [1, 1280, 7, 7] 5,120
ReLU6-280 [[1, 1280, 7, 7]] [1, 1280, 7, 7] 0
AdaptiveAvgPool2D-8 [[1, 1280, 7, 7]] [1, 1280, 1, 1] 0
Dropout-8 [[1, 1280]] [1, 1280] 0
Linear-8 [[1, 1280]] [1, 4] 5,124
================================================================================
Total params: 2,263,108
Trainable params: 2,194,884
Non-trainable params: 68,224
--------------------------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 152.87
Params size (MB): 8.63
Estimated Total Size (MB): 162.08
--------------------------------------------------------------------------------
{'total_params': 2263108, 'trainable_params': 2194884}
# 训练模式
model.evaluate(val_dataset)
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 10/221 - loss: 0.5310 - acc: 1.0000 - 42ms/step
step 20/221 - loss: 0.4472 - acc: 1.0000 - 40ms/step
step 30/221 - loss: 0.5541 - acc: 0.9667 - 40ms/step
step 40/221 - loss: 0.4161 - acc: 0.9750 - 40ms/step
step 50/221 - loss: 0.4183 - acc: 0.9600 - 40ms/step
step 60/221 - loss: 0.3530 - acc: 0.9000 - 39ms/step
step 70/221 - loss: 0.3697 - acc: 0.8714 - 39ms/step
step 80/221 - loss: 0.4089 - acc: 0.8875 - 39ms/step
step 90/221 - loss: 0.4297 - acc: 0.9000 - 39ms/step
step 100/221 - loss: 0.3681 - acc: 0.9000 - 39ms/step
step 110/221 - loss: 0.3649 - acc: 0.9091 - 39ms/step
step 120/221 - loss: 0.4460 - acc: 0.9083 - 38ms/step
step 130/221 - loss: 0.3587 - acc: 0.9077 - 38ms/step
step 140/221 - loss: 0.4590 - acc: 0.9143 - 38ms/step
step 150/221 - loss: 0.3798 - acc: 0.9200 - 38ms/step
step 160/221 - loss: 0.4298 - acc: 0.9187 - 39ms/step
step 170/221 - loss: 0.4803 - acc: 0.9235 - 39ms/step
step 180/221 - loss: 0.8577 - acc: 0.9222 - 39ms/step
step 190/221 - loss: 2.1528 - acc: 0.9211 - 39ms/step
step 200/221 - loss: 2.0429 - acc: 0.9200 - 39ms/step
step 210/221 - loss: 0.7216 - acc: 0.9238 - 38ms/step
step 220/221 - loss: 2.1792 - acc: 0.9227 - 38ms/step
step 221/221 - loss: 0.3522 - acc: 0.9231 - 38ms/step
Eval samples: 221
{'loss': [0.35224038], 'acc': 0.9230769230769231}
import os, time
import matplotlib.pyplot as plt
import paddle
from PIL import Image
import numpy as np
def load_image(img_path):
'''
预测图片预处理
'''
img = Image.open(img_path).convert('RGB')
#plt.imshow(img) #根据数组绘制图像
#plt.show() #显示图像
#resize
img = img.resize((224, 224), Image.BILINEAR) #Image.BILINEAR双线性插值
img = np.array(img).astype('float32')
# HWC to CHW
img = img.transpose((2, 0, 1))
#Normalize
img = img / 255 #像素值归一化
mean = [0.31169346, 0.25506335, 0.12432463]
std = [0.34042713, 0.29819837, 0.1375536]
img[0] = (img[0] - mean[0]) / std[0]
img[1] = (img[1] - mean[1]) / std[1]
img[2] = (img[2] - mean[2]) / std[2]
return img
def infer_img(path, model_file_path, use_gpu):
'''
模型预测
'''
paddle.set_device('gpu:0') if use_gpu else paddle.set_device('cpu')
model = paddle.jit.load(model_file_path)
model.eval() #训练模式
#对预测图片进行预处理
infer_imgs = []
infer_imgs.append(load_image(path))
infer_imgs = np.array(infer_imgs)
label_list = ['0:優良', '1:良', '2:加工品', '3:規格外']
label_pre = []
for i in range(len(infer_imgs)):
data = infer_imgs[i]
dy_x_data = np.array(data).astype('float32')
dy_x_data = dy_x_data[np.newaxis,:, : ,:]
img = paddle.to_tensor(dy_x_data)
out = model(img)
# print(out[0])
# print(paddle.nn.functional.softmax(out)[0]) # 若模型中已经包含softmax则不用此行代码。
lab = np.argmax(out.numpy()) #argmax():返回最大数的索引
label_pre.append(lab)
# print(lab)
print("样本: {},被预测为:{}".format(path, label_list[lab]))
return label_pre
# print("*********************************************")
2021-03-10 22:32:00,127 - INFO - font search path ['/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf', '/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/afm', '/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/pdfcorefonts']
2021-03-10 22:32:00,596 - INFO - generated new fontManager
model.save('MyCNN', False)
infer_img(path='data/data72793/lemon_homework/lemon_lesson/test_images/test_0831.jpg',model_file_path='MyCNN',use_gpu=1)
样本: data/data72793/lemon_homework/lemon_lesson/test_images/test_0831.jpg,被预测为:2:加工品
[2]
# 保存预测结果
import os
import csv
zemax = []
def create_csv_2(dirname):
path = 'data/data72793/lemon_homework/lemon_lesson'+ dirname +'/'
name = os.listdir(path)
with open (dirname+'.csv','w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['id', 'label'])
for n in name:
if n[-4:] == '.jpg':
#print(n)
zemax = infer_img(path='data/data72793/lemon_homework/lemon_lesson/test_images/'+ n,model_file_path='MyCNN',use_gpu=1)
writer.writerow([str(n),zemax[0]])
else:
pass