主要环境配置
win10,pycharm
Python3.6
keras2.2.0
numpy1.16.0
pillow8.1.1
scipy1.5.4
tensorflow-gpu1.11.0
先使用自己的配置,没有问题的话就不用更改
数据介绍
Fruits 360
A dataset with 90483 images of 131 fruits and vegetables
每张图片:100x100,真彩(3通道)
数据获取
数据来自于网上公开数据集
https://www.kaggle.com/moltean/fruits
或者,数据及源码:(源码包括两种方式编写的经典卷积神经网络LeNet-5模型)
链接:https://pan.baidu.com/s/1iKSZTu4cPM8d-VxnH4Xx8A
提取码:06wk
另外,人工智能入门四件套免费分享(统计学习方法、机器学习、机器学习实战、深度学习)
链接:https://pan.baidu.com/s/1kG3cRvto75krhjz1Ow4ANw 提取码:b8r1
库引用
import os
from skimage import io
import numpy as np
from sklearn.utils import shuffle
import keras
import tensorflow as tf
数据载入
原来的数据集有131种分类,为了节省训练时间方便学习,分别建了一个用于训练和测试的文件夹,把想要训练的分类从原数据文件夹拷到里面
dir_path1 = 'fruits-360/Training1'
dir_path2 = 'fruits-360/Test1'
#读取数据
def load_data(dir_path):
images = []
labels = []
file = os.listdir(dir_path) #返回一个列表:包含dir_path里的文件名,即分类
n_classes = len(file) #分类数量
n = 0
for l in file:
img = os.listdir(dir_path+'/'+ l)
for i in img:
img_path = dir_path+'/'+ l+'/'+ i
labels.append(int(n))
images.append(io.imread(img_path))
n += 1
return images,labels,n_classes
images,labels,n_classes = load_data(dir_path1)
images_test,labels_test,_ = load_data(dir_path2)
print("种类:",n_classes)
数据预处理
仅进行数组化,打乱顺序,标签转换为独热编码
#数据预处理:
def data_processing(images,labels,n_classes):
train_x = np.array(images)
train_y = np.array(labels)
indx = np.arange(0,train_y.shape[0])
indx = shuffle(indx) #随机打乱
train_x = train_x[indx]
train_y = train_y[indx]
train_y = keras.utils.to_categorical(train_y,n_classes) #转为Onehot标签
return train_x,train_y
train_x,train_y = data_processing(images,labels,n_classes)
test_x,test_y = data_processing(images_test,labels_test,n_classes)
搭建模型
经典的卷积神经网络LeNet-5模型,使用全局平均池化层代替全连接层,并使用了高级库contrib简洁代码。即源码中的(4)。
神经网络参数配置
batch_size = 32
dropout = 0.8
training_epochs = 5
learningrate = 0.001
filter_height = 5
filter_width = 5
in_channels = 3
out_channels1 = 32
out_channels2 = 64
image_size = train_x.shape[1] ##图片尺寸
total_data_num = train_x.shape[0]
stride1 = 2
stride2 = 2
x = tf.placeholder(tf.float32,[None,image_size,image_size,in_channels])
tf.summary.image('x',x,max_outputs=10)
y = tf.placeholder(tf.float32,[None,n_classes])
tf.summary.histogram('y',y)
keep_prob = tf.placeholder(tf.float32)
卷积神经网络结构搭建
def conv_net(x,dropout):
##卷积层1
h_conv1 = tf.contrib.layers.conv2d(x,out_channels1,[filter_height,filter_width],1,'SAME',activation_fn=tf.nn.relu)
h_pool1 = tf.contrib.layers.max_pool2d(h_conv1,[stride1,stride1],stride=stride1,padding='SAME')
##卷积层2
h_conv2 = tf.contrib.layers.conv2d(h_pool1,out_channels2,[filter_height,filter_width],1,'SAME',activation_fn=tf.nn.relu)
h_pool2 = tf.contrib.layers.max_pool2d(h_conv2, [stride2, stride2], stride=stride2, padding='SAME')
## Dropout(Dropout层防止预测数据过拟合)
conv2 = tf.nn.dropout(h_pool2, dropout)
## 全局平均池化层
avg_pool = tf.contrib.layers.conv2d(conv2,n_classes,[filter_height,filter_width],1,'SAME',activation_fn=tf.nn.relu)
prediction = tf.contrib.layers.avg_pool2d(avg_pool, [25, 25], stride=25, padding='SAME')
return tf.reshape(prediction, [-1, n_classes])
# 优化预测准确率
prediction = conv_net(x,keep_prob)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=prediction, labels=y)) ##交叉熵损失函数
tf.summary.scalar('loss_function',loss)
optimizer = tf.train.AdamOptimizer(learningrate).minimize(loss) ##优化器
correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
tf.summary.scalar('accuracy',accuracy)
保存模型
saver = tf.train.Saver()
savedir = 'log/model'
初始化会话并开始训练
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
merged_summary_op = tf.summary.merge_all()
summary_writer = tf.summary.FileWriter('log/summaries',sess.graph)
# 启动循环开始训练
for epoch in range(training_epochs):
total_batch = int(total_data_num / batch_size)
# 遍历全部数据集
for i in range(total_batch):
batch_x, batch_y = train_x[i * batch_size:batch_size * (i + 1), :], train_y[
i * batch_size:batch_size * (i + 1), :]
_, acc, Loss = sess.run([optimizer, accuracy, loss], feed_dict={x: batch_x, y: batch_y, keep_prob: dropout})
# Compute average loss
print("Epoch:", '%04d' % (epoch + 1), "cost=", "{:.9f}".format(Loss), "Training accuracy",
"{:.5f}".format(acc))
summary_str = sess.run(merged_summary_op,feed_dict={x: batch_x, y: batch_y, keep_prob: dropout})
summary_writer.add_summary(summary_str,epoch) #Tensorboard可视化
print(" Finished!")
saver.save(sess,'log/model')
# 测试 model
test_feed = {x: test_x[0:100], y: test_y[0:100], keep_prob: 1}
print('Testing Accuracy:', sess.run(accuracy, feed_dict=test_feed))
运行结果
本次是进行了37种水果分类。
测试准确率
Tensorboard显示
节选输入图片
损失函数
载入模型使用
#载入模型
with tf.Session() as sess2:
sess2.run(tf.global_variables_initializer())
saver.restore(sess2,savedir)
test_feed = {x: test_x[200:300], y: test_y[200:300], keep_prob: 1}
print('Testing Accuracy:', sess2.run(accuracy, feed_dict=test_feed))
记录自己的学习之路,发现问题请不吝赐教,多多交流。