logo头像

猪老大要进步!

TensorFlow 2.0:建立图像分类网络

本文于 1214 天之前发表,文中内容可能已经过时。

既然google官方已经推出了tensorflow2.0的正式版,tensorflow的一些新特性让他变得更加便于使用,未来必将取代tensorflow1.x系列,为了避免被淘汰。我开始尝试tensorflow2.0,这是第一篇关于tensorflow2.0的文章,内容是使用tensotflow2.0实现一个图像分类卷积网络。

keras作为tensorflow的一个子模块添加到里面,故可以方便地调用,和1.x版本里面使用keras没有太大什么区别,有变化的地方我会在下面写出来。

这一次我们还是循规蹈矩地做一个三分类的网络。

1、预读取训练数据

图片数据的预读取可以参照我之前一篇文章《神经网络训练–数据预读取和存储》,但是这里因为tensorflow2.0里面集成的keras特性,训练时采用的labels不可以是独热编码(one-hot label),取而代之的是索引值,因此需要对预读取的代码进行修改。

这样一来,操作上确实是简单了一些,但是代价是逻辑上的不直观。我个人觉得得不偿失。

修改的部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 载入库
from skimage.io import imread
from skimage.transform import resize
import os
import numpy as np

# 路径下图片读取,给与标签
def load_images(path,reshape=224):
contents = os.listdir(path)
classes=[each for each in contents if os.path.isdir(os.path.join(path,each))]
print('目录下有%s' % classes)
# 用labels来存储图片的类别
labels = []
# images数组用来存储图片数据
images = []
i = 0
# 对每个不同种类读取图片到list并且+标签
for i,each in enumerate(classes,0):
class_path = os.path.join(path,each)
files = os.listdir(class_path)
print("Starting {} images".format(each),'数量为',len(files))
for file in files:
# 载入图片并放入batch数组中
img = imread(os.path.join(class_path, file))
img = img / 255.0
# 这里输入的是图片的缩放尺寸
img = resize(img, (reshape, reshape))
images.append(img.reshape((reshape,reshape,3)))
labels.append(i)
images = np.array(images)
labels = np.array(labels)
print('总共读取了%d张图片'%images.shape[0])
return images,labels # 返回图片以及对应的标签

path='../三类图片/'
train_x,train_y = load_images(path)

# 以.npy格式存储在当前目录下
np.save("train_x.npy",train_x)
np.save("train_y.npy",train_y)

2、训练程序部分

主要是以下几个步骤:

  • 载入库
  • 读取训练数据
  • 构建神经网咯模型
  • 开始训练
  • 训练过程可视化

下面是源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env python
# coding: utf-8

# 载入库
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Conv2D, Dropout, MaxPooling2D
from tensorflow.keras import Model,Sequential
import matplotlib.pyplot as plt
import numpy as np

# 载入训练数据
train_x = np.load("train_x.npy")
train_y = np.load("train_y.npy")

# 展示一个图片作为样本看看
plt.imshow(train_x[0])
plt.show()
print(train_x.shape)
print(train_y.shape)

# 模型构建
model = Sequential()
model.add(Conv2D(32, 3, activation='relu', input_shape=(224, 224, 3)))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, 3, activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, 3, activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(128, 3, activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(128, 3, activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(1024,activation='relu'))
model.add(Dense(1024,activation='relu'))
model.add(Dense(3,activation='softmax'))

# 模型编译
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 开始训练
history = model.fit(train_x, train_y, batch_size=20, epochs=5)
# 可视化
l = np.array(history.history['loss'])
a = np.array(history.history['accuracy'])
step = np.linspace(1,50,50)
plt.plot(step,l,label="Train Loss")
plt.legend(loc='upper right')
plt.title('epoch-loss')
plt.xlim((0, 50))
plt.gca().set_ylim(bottom=0)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()
plt.plot(step,a,label="Train Acc")
plt.legend(loc='lower right')
plt.title('epoch-acc')
plt.xlim((0, 50))
plt.gca().set_ylim(bottom=0)
plt.xlabel('epoch')
plt.ylabel('acc')
plt.show()

Reference:

1、Convolutional Neural Network (CNN)

2、我的Github仓库源码

支付宝打赏 微信打赏

赞赏是不耍流氓的鼓励