用TensorFlow实现对植物的六分类(水了一篇完全没用,大佬绕道)


前言

想要接触机器学习,但是无奈数学基础不是很好,看了很多参考资料,最后发现如果不需要自己实现底层的话只需要调用TensorFlow就可以了,最后就变成了TensorFlow的学习了

参考资料

  1. 《机器学习》 周志平
    机器学习的数学基础,虽然看哭了,但是真的能让你理解框架里的函数,用来干啥的
  2. 《机器学习实战(Machine Learning in Action 中文版)》 Peter Harrington
    非神经网络的实操神书

  3. 《hands-on-ml-with-sklearn-and-tf》Aurelien gero
    神经网络的实操神书,特别是教导了TensorFlow的使用方法

  4. 中文官网

  5. TensorFlow进行花朵分类

  6. TensorFlow猫狗大战

安装踩坑

这个必须写在前面,我是用GPU来跑TensorFlow的,所以用的是GPU版本,下面是我的环境

  1. 环境基础 pycharm ,win10(不是linux大家可放心)

  2. python 3.6 x64(这点很重要,不是64位TensorFlow会报错,你还不知道为什么,坑了半天)

  3. tensorflow-gpu 1.12(不要下载最新版本,你会落泪的,因为最新版本,没有告诉你你需要版本的依赖环境)

  4. CUDA 9.0

  5. cudnn 9.0
    以上两个就是依赖项,必须和TensorFlow版本匹配(不要问问我为什么知道那么多)

  6. 其余你看到的包,你就直接在pycharm中安装就好了,可视化很方便

代码解读(只有关键代码)

因为我的代码也是由例子改的,但是修改的困难只有自己才知道,目的就是如果大家如果希望写一个样本分类不是那么多的机器学习可以按照我的稍微调整参数即可(希望大家去看看数学基础再来),顺便也为了自己未来可以捡起来可以回头看看

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
#handle picture,这个图片处理很好用值得收藏,各个地方都用得到

from skimage import io, transform, color
import os
import numpy as np

def read_img(path):
imgs = []
labels = []
classs = os.listdir(path)

for idx, folder in enumerate(classs):
# enumerate() 函数用于将一个可遍历的数据对象,如文件夹里有apple,就返回["1","apple"],在这里就相当于做了整个文件夹图片的标签
cate = os.path.join(path, folder)
for im in os.listdir(cate):
img_path =os.path.join(cate, im)

img = io.imread(img_path)
img = color.rgb2gray(img)
#这里为了运算速率,以及降维等,用灰度图片
img = transform.resize(img, (w, h))
#将图片统一大小这样在网络中才能正常运算(失帧问题不大)
imgs.append(img)
labels.append(idx)
return np.asarray(imgs, np.float32), np.asarray(labels, np.int32)
#将信息以数组的方式返回
1
2
3
4
5
6
7
8
9
10
11
def batch_norm(x, momentum=0.9, epsilon=1e-5, train=True, name='bn'):
return tf.layers.batch_normalization(
x,
# 输入input
momentum=momentum,
epsilon=epsilon,
# 给variance加一个小浮点数以避免除以零
scale=True,
#如果为True,则乘以gamma
training=train,#为true才会运行
name=name)
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
65
66
67
68
x = tf.reshape(x,[-1,100,100,1]) #必须要是四维的tensor才可以在conv2d处理,所以resize
# 第一个卷积层(100->50)
conv1 = tf.layers.conv2d(
inputs=x,
filters=32,#维度
kernel_size=[3, 3],#内核数
padding="same",
activation=tf.nn.relu,#激活函数
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
conv1 = batch_norm(conv1, name='pw_bn1')
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)#池化

# 第二个卷积层(50->25)
conv2 = tf.layers.conv2d(
inputs=pool1,
filters=64,
kernel_size=[3, 3],
padding="same",
activation=tf.nn.relu,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
conv2 = batch_norm(conv2, name='pw_bn2')
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)#池化

# 第三个卷积层(25->12)
conv3 = tf.layers.conv2d(
inputs=pool2,
filters=128,
kernel_size=[3, 3],
padding="same",
activation=tf.nn.relu,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
conv3 = batch_norm(conv3, name='pw_bn3')

pool3 = tf.layers.max_pooling2d(inputs=conv3, pool_size=[2, 2], strides=2)#池化

# 第四个卷积层(12->6)
conv4 = tf.layers.conv2d(
inputs=pool3,
filters=128,
kernel_size=[3, 3],
padding="same",
activation=tf.nn.relu,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
conv4 = batch_norm(conv4, name='pw_bn4')

pool4 = tf.layers.max_pooling2d(inputs=conv4, pool_size=[2, 2], strides=2)#池化

re1 = tf.reshape(pool4, [-1, 6 * 6 * 128])

# 全连接层
dense1 = tf.layers.dense(inputs=re1,
units=1024,
activation=tf.nn.relu,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
dense2 = tf.layers.dense(inputs=dense1,
units=512,
activation=tf.nn.relu,
#正太分布的初始化,stddev:一个标量张量,要生成的随机值的标准偏差. kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))#正则化项的损失函数,参数是权重
#未归一化概率
logits = tf.layers.dense(inputs=dense2,
units=6,
activation=None,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
pred = tf.nn.softmax(logits, name='prob') #进行预测
return logits, pred

接下来就是调用的问题了,还有就是模型保存和使用的代码了

1
2
3
4
5
6
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()#用于保存模型
writer = tf.summary.FileWriter("./logs", sess.graph)#这里就是利用tensorboard来可视化

saver.save(sess, "./model/save_net.ckpt",epoch)#在指定目录保存模型

这里是预测代码

1
2
3
4
5
6
7
with tf.Session() as sess:
ckpt = tf.train.get_checkpoint_state(ckpt_dir)
saver.restore(sess, ckpt.model_checkpoint_path)
classes_ = sess.run(pred,feed_dict={ imgs_holder: np.reshape(image_data , [1, w, h])})

num = np.argmax(classes_)
print('the test image is :',classes[int(num)],' Probability is :',classes_[0][int(num)])

后记

感觉水了一篇,因为自己记忆力不好,才出现的博客,2333333,大家可以无视绕过