深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)

1.cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)

参数说明:image表示输入图片,image_size表示变化后的图片大小,0, 0表示dx和dy, cv2.INTER_LINEAR表示插值的方式为线性插值

2.image.get_shape[1:4].num_elements() 获得最后三个维度的大小之和

参数说明:image表示输入的图片

3. saver.save(sess, path, global_step=i) 进行sess的加载

参数说明:sess表示输入,path表示保存路径, global_step表示路径的结尾

4.saver = tf.train.import_meta_graph('./dog-cats-model/dog-cat.ckpt-3700.meta')  # 加载训练好的模型的meta值

参数说明:./dog-cats-model/dog-cat.ckpt-3700.meta表示meta 的路径

5.saver.restore(sess, ckpt_path) # 加载训练好的参数模型

参数说明:sess表示执行函数,ckpt_path表示ckpt的路径

6.graph = tf.get_defualt_graph 获得训练好的参数图

7.graph.get_tensor_by_name('x:0') 获得模型的占位参数,以便进行模型的预测

参数说明:’x:0‘ 表示模型在训练过程中,tf.placeholder(name=’x') 输入数据设置的名字

代码中的学习点:1. 使用cv2.resize对图片的维度进行压缩

2.使用np.zeros(num_classes)构造标签,lable[index] = 1 构造标签

3.使用image.get_shape[1:4].num_elements获得最后三个维度的大小

4. saver.save(sess, path, global_step=i) 进行模型参数的存储

5.save.restore(sess, path)  进行模型的加载

猫狗识别的代码:主要分为3个部分,

第一部分:数据的准备

第二部分:构造卷积神经网络,进行模型的训练

第三部分:使用saver.restore加载训练好的参数,进行模型的预测。

第一部分:数据的准备,构建read_train_data函数

第一步:输入的参数是文件的地址,图片的大小(进行图像的矩阵变换),标签,验证集的比例

第二步:对构造一个类dataset, 用于存储训练集和验证集

第三步:对标签进行循环,对输入的文件与标签值进行拼接,获得图片文件的地址,使用glob.glob获得每张图片的地址。

第四步:循环图片地址,读入图片

第一步:使用cv2.imread() 读入图片

第二步: 使用cv2.resize(img, (img_size, img_size), 0, 0, cv2.Inter) 进行图片的维度变换

第三步: 使用.astype('float32') 对图片进行数据类型的转换

第四步: 使用np.multiply(img, 1.0/255.0) 进行图片数值归一化操作, 并将图片加到列表中

第五步:使用np.zeros(num_classes) 构造标签的零矩阵

第六步:使用index = classes.index(filed) 获得标签值对应的索引,label[index] = 1 将索引位置赋值为1

第七步: 将标签加到列表中

第八步:使用os.path.basename(file) 获得图片的名字,添加到列表中,获得标签的名字,添加到列表中

第五步:对图片和标签使用np.array转换为数组类型,并返回图片,标签,名字,类别名

第六步:使用sklearn.utils 中的shuffle,对图片,标签,名字和类别名进行清洗

第七步:使用val_size,验证集的比例对训练集和验证集进行分割

第八步:创建类别DataSet,实例化dataset.train和dataset.val,创建.next_batch函数,

第九步:next_batch函数说明:使用一个变量self._epoch_index 对start和end进行递增循环,如果end > self._num_image, 将start置为0, self._epoch_index置为batch_size。

代码:dataset.py

import numpy as np
import tensorflow as tf
import os
import glob
import cv2
from sklearn.utils import shuffle def load_image(file_path, image_size, classes): num_classes = len(classes)
images = []
labels = []
names = []
cls = []
# 第三步:循环标签,将路径和标签名进行拼接,获得图片文件路径,使用glob.glob获得图片路径
for filed in classes:
index = classes.index(filed)
path = os.path.join(file_path, filed, '*g')
files = glob.glob(path)
# 第四步:循环图片路径,进行图片的读取
for file in files:
# cv2.imread图片的读取
image = cv2.imread(file)
# cv2.resize进行图片维度的重构
image = cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)
# .astype进行图片的数据类型的变换
image = image.astype('float32')
# 使用np.multipy进行图片的归一化操作
image = np.multiply(image, 1.0/255.0)
# 将图片添加到列表中
images.append(image)
# 标签零值初始化
label = np.zeros(num_classes)
# 对于类别位置与标签位置对应,即设置为1
label[index] = 1
# 将标签进行添加
labels.append(label)
# 获得图片的名字,使用os.path.basename
name = os.path.basename(file)
# 将名字进行添加
names.append(name)
# 将类别名进行添加
cls.append(filed)
# 第五步: 将图片和标签名都转换为array格式, 并返回图片,标签,名字和类别
images = np.array(images)
labels = np.array(labels) return images, labels, names, cls class DataSet(object): def __init__(self, images, labels, names, cls): self._num_image = images.shape[0]
self._images = images
self._labels = labels
self._names = names
self._cls = cls
self._epoch_index = 0
# 私有属性,返回实际的函数值
@property
def images(self):
return self._images
@property
def labels(self):
return self._labels
@property
def names(self):
return self._names
@property
def cls(self):
return self._cls
@property
def num_image(self):
return self._num_image
# next_batch函数,使用self._epoch_index用来创建初始索引和结束索引,返回batch图像,标签,名字和类别
def next_batch(self, batch_size):
start = self._epoch_index
self._epoch_index += batch_size
if self._epoch_index > self._num_image:
start = 0
self._epoch_index = batch_size
assert batch_size < self._num_image
end = self._epoch_index
return self._images[start:end], self._labels[start:end], self._names[start:end], self._cls[start:end] # 第一步:输入文件名,图片大小,标签,验证集的比例
def read_train_data(file_path, image_size, classes, val_size):
# 第二步:构造类,实例化dataset用于存储训练集和验证集
class DataSets(object):
pass
dataset = DataSets()
# 第三步:载入图片,标签, 名字,类别名
images, labels, names, cls = load_image(file_path, image_size, classes)
# 第六步:对图片,标签,名字和类别名进行清洗
images, labels, names, cls = shuffle(images, labels, names, cls)
# 第七步:使用val_size 对训练集和验证集图片进行分开
val_num = int(images.shape[0] * val_size) val_images = images[0:val_num]
val_labels = labels[0:val_num]
val_names = names[0:val_num]
val_cls = cls[0:val_num] train_images = images[val_num:]
train_labels = labels[val_num:]
train_names = names[val_num:]
train_cls = cls[val_num:]
# 第八步:创建类别DataSet,实例化train和val数据集,并创建next_batch
dataset.train = DataSet(train_images, train_labels, train_names, train_cls)
dataset.val = DataSet(val_images, val_labels, val_names, val_cls) return dataset

第二步:模型的训练

第一步:参数设置,一二三层卷积的大小和个数,以及全连接层的隐藏层的个数

第二步:使用tf.placeholder设置初始的输入参数x和y_pred,并命名为x和y_pred, 使用np.argmax获得预测的索引值

第三步:构建生成卷积过程中参数的函数, tf.Variable(tf.truncate_normal(shape, stddev=0.05))

第四步:构建进行卷积的函数,使用tf.nn.conv2(x, w, stride=[1, 2, 2, 1], padding='SAME'),再加上偏置项b, 使用激活层tf.nn.relu构建, 使用tf.nn.max_pool构建池化层

第五步:构建进行维度变换的函数,用于进行第一次全连接层的卷积到全连接的维度变换,使用image.get_shape()[1:4].num_elements获得后3个维度的个数之和,即乘积

第六步:构造进行全连接的函数,使用tf.matmul构造全连接函数,这里的话,需要使用tf.nn.dropout进行dropout防止过拟合

第七步:开始进行卷积过程

第一步:第一层卷积

第二步:第二层卷积

第三步:第三次卷积

第四步:第一次全连接,使用conv.get_shape[1:4].num_elements获得维度,构造参数

第五步:第二次全连接

第八步:y_pred = tf.nn.softmax构造y_pred, 使用tf.argmax(y_pred, 1)输出索引值

第九步:使用tf.nn.softmax_logits构造损失值loss, logits=score, labels= y_true

第十步:使用tf.train.Adaoptimer().minimize自适应梯度下降降低损失值

第十一步:使用tf.equal(y_pred_cls, y_true_cls) ,tf.reduce_mean构造准确率

第十二步:构建train函数, 开始进行训练,首先使用data.train.next_batch获得batch训练样本,使用sess.run训练trainopt降低损失值,进行参数的训练

第十三步:每一个epoch值,获得train 的batch,获得val_batch,对训练集和验证集的准确率进行展示

代码:train.py

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import dataset from numpy.random import seed seed(0) from tensorflow import set_random_seed set_random_seed(20) image_size = 60
val_size = 0.2
file_path = 'training_data'
classes = ['cats', 'dogs']
num_channel = 3
num_classes = len(classes) # 第一部分数据的载入
data = dataset.read_train_data(file_path, image_size, classes, val_size) image_num = data.train.images.shape[0]
# 第二部分:数据的实际训练 # 第一步参数设置,卷积层的维度和filter的个数
# 第一层卷积大小
filter1_size = 3
filter1_num = 32
# 第二层卷积大小
filter2_size = 3
filter2_num = 32
# 第三层卷积大小
filter3_size = 3
filter3_num = 64
# 隐含层大小
fc1_num = 1024
# 第二步:使用tf.placeholder设置初始输入参数
# 输入参数大小, [图片的数目,图片的宽度, 图片的长度, 图片的通道数]
x = tf.placeholder(tf.float32, [None, image_size, image_size, num_channel], name='x')
# 输入图片标签值,大小为[N, num_classes] 这里为N*2
y_true = tf.placeholder(tf.float32, [None, num_classes], name='y_true')
#真实类别对应的索引值,即1所在的位置
y_true_cls = tf.argmax(y_true, 1) # 第三步:生成卷积过程中所需要的函数
def create_weight(shape):
# 生成正态分布的初始值
return tf.Variable(tf.truncated_normal(shape, stddev=0.05)) def create_bias(size):
# 生成常数分布的初始值
return tf.Variable(tf.constant(0.05, shape=[size]))
# 第四步:构造进行卷积的函数
def create_convolution_layers(input, input_channel, filter_size, filter_num):
# 生成卷积使用的W,[3, 3, 3, 32]第一层卷积核大小
W = create_weight([filter_size, filter_size, input_channel, filter_num])
# 生成偏置项b [32]
b = create_bias(filter_num)
# 进行卷积操作
conv_layer = tf.nn.conv2d(input, W, strides=[1, 1, 1, 1], padding='SAME') + b
# 进行激活操作
conv_layer = tf.nn.relu(conv_layer)
# 使用tf.nn.max_pool进行池化操作
max_pool = tf.nn.max_pool(conv_layer, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 返回池化的结果
return max_pool
# 第五步:构造图像变换的函数
def create_flatten_conv(input):
# 获得图片的后3个维度的大小
input_shape = input.get_shape()[1:4].num_elements()
# 对图像进行维度的变化,即[-1, input_shape] 以便用于后续的全连接操作
out = tf.reshape(input, shape=[-1, input_shape]) return out
# 第六步:构造进行全连接变化的函数
def create_fc_layer(input, num_input, fc1_num, relu_true = True):
# 构造全连接的函数,即后三个维度的大小和第一个全连接的大小
W = create_weight([num_input, fc1_num])
# 构造偏置项b
b = create_bias(fc1_num)
# 构造线性变化,即x * w + b
layer = tf.matmul(input, W) + b
# 对全连接层进行dropout变化
layer = tf.nn.dropout(layer, keep_prob=0.7)
# 如果需要进行激活层
if relu_true:
# 就进行激活变化
layer = tf.nn.relu(layer)
# 返回结果
return layer
# 第七步:进行正式的卷积过程
# 第一层卷积,输入为x, 通道数,卷积核的大小,卷积的个数
conv_h1 = create_convolution_layers(x, num_channel, filter1_size, filter1_num)
# 第二层卷积
conv_h2 = create_convolution_layers(conv_h1, filter1_num, filter2_size, filter2_num)
# 第三层卷积
conv_h3 = create_convolution_layers(conv_h2, filter2_num, filter3_size, filter3_num)
# 获得第三层卷积后的后3个维度的大小
flatten_shape = conv_h3.get_shape()[1:4].num_elements()
# 对图像进行维度变化
flatten_conv = create_flatten_conv(conv_h3)
# 进行全连接操作,输入的是变换后的图像,全连接的第一个维度和第二个维度
fc_h1 = create_fc_layer(flatten_conv, flatten_shape, fc1_num)
# 进行第二次全连接,输出预测的得分值
out = create_fc_layer(fc_h1, fc1_num, num_classes, relu_true=False)
# 第八步:使用tf.nn.softmax获得输入得分的概率值
y_pred = tf.nn.softmax(out, name='y_pred')
# 使用tf.agrmax获得对应的最大索引的大小
y_pred_cls = tf.argmax(y_pred, 1)
# 第九步:使用tf.reduce_mean获得softmax的损失值
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=out))
# 第十步:使用自适应梯度下降,进行损失值的下降
train_op = tf.train.AdamOptimizer(0.0001).minimize(cost)
# 第十一步:使用tf.equal表示类别是否相同
correct_pred = tf.equal(y_true_cls, y_pred_cls)
accur = tf.reduce_mean(tf.cast(correct_pred, 'float')) # 构造session函数
session = tf.Session()
# 构造存储函数
saver = tf.train.Saver()
# 进行初始化操作
session.run(tf.global_variables_initializer()) batch_size = 32 def show_progress(data, lost, epoch, i): tr_image_batch, tr_label_batch = data.train.next_batch(batch_size)[0:2]
val_image_batch, val_label_batch = data.val.next_batch(batch_size)[0:2]
# 输出训练样本的准确率
tr_accur = session.run(accur, feed_dict={x:tr_image_batch, y_true:tr_label_batch})
# 输出验证样本的准确率
val_accur = session.run(accur, feed_dict={x:val_image_batch, y_true:val_label_batch})
# 打印epoch值,训练集和验证集准确率,训练的损失值,迭代的次数
content = ('train_epoch {0} tr_accur {1:>6.1%} val_accur {2:6.1%} train_loss {3:.3f} iteration_num {4}')
print(content.format(epoch, tr_accur, val_accur, lost, i))
def train(num_iteration):
start_epoch = 0
for i in range(num_iteration):
# 第十二步:构造函数进行参数的实际代入,使用data.train.next_batch获得模型的训练样本和验证集样本,进行模型训练
batch_image, batch_labels, batch_nams, batch_cls = data.train.next_batch(batch_size)
session.run(train_op, feed_dict={x:batch_image, y_true:batch_labels})
#第十三步:每一个epoch进行模型的准确率的输出
if i % int(data.train.num_image / batch_size) == 0:
# 计算模型的损失值
loss = session.run(cost, feed_dict={x:batch_image, y_true:batch_labels})
# 展示模型的训练集和验证集的准确率
show_progress(data, loss, start_epoch, i)
start_epoch += 1
# 第十四步:使用saver.save(session, './dog-cats-model/dog-cat.ckpt', global_step)进行模型的参数保存
saver.save(session, './dog-cats-model/dog-cat.ckpt', global_step=i) train(8000)

深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)

第三部分:进行模型的预测

第一步:图片的输入,对于输入的图片需要进行与训练样本输入时相同的处理

第一步:使用cv2.imread()进行样本的读取

第二步:使用cv2.resize进行图片的维度变换

第三步:.astype对样本的类型进行变换

第四步:使用np.multipy对样本进行归一化操作

第五步:将图片的维度进行变换,因为是一张图片,维度变化为[1, 60, 60, 3]

第二步:将训练好的模型进行加载

第一步:构建sess = tf.Session() 
              第二步:使用saver = tf.train.import_meta_graph 加载模型的meta

第三步:使用saver.restore() 加载模型的ckpt-3750

第四步:graph = tf.get_default_graph()获得参数结构图

第五步:使用graph.get_tensor_by_name('y_pred:0') 获得预测y_pred

第五步:使用graph.get_tensor_by_name('x:0') 获得输入x

第六步:使用graph.get_tensor_by_name('y_pred:0') 获得输入标签y_true

第七步:使用np.zeros((1, 2))构造输入值得标签

第八步:使用sess.run(y_pred, feed_dict={x:x_batch, y_pred:y_test_img}) 进行结果的预测

第九步:使用tf.argmax获得标签的索引,使用标签名获得最终的预测结果

代码:predict.py

import tensorflow as tf
import numpy as np
import cv2 # 第一步图片的载入
image_size = 60
# 图片的文件名
path = 'cat.4.jpg'
# 读取图片
image = cv2.imread(path)
# 改变图片的大小
image = cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)
# 图片类型的转换
image = image.astype('float32')
# 进行图像的归一化
image = np.multiply(image, 1.0/255.0)
# 对图像进行维度的变化
x_batch = image.reshape(1, image_size, image_size, 3) # 加载模型,对图片进行预测
# 初始化sess
sess = tf.Session()
# 载入saver,获得模型的结果saver
saver = tf.train.import_meta_graph('./dog-cats-model/dog-cat.ckpt-3700.meta')
# 使用saver加载sess
saver.restore(sess, './dog-cats-model/dog-cat.ckpt-3700')
# 获得模型的结构图
graph = tf.get_default_graph()
# 使用结构图获得模型参数y_pred
y_pred = graph.get_tensor_by_name('y_pred:0')
# 获得模型参数x
x = graph.get_tensor_by_name('x:0')
# 获得模型参数y_true
y_true = graph.get_tensor_by_name('y_true:0')
# 构造真实的标签值,初始化
y_test_images = np.zeros((1, 2))
# 输入的样本参数
feed_dict_testing = {x:x_batch, y_pred:y_test_images}
# 获得模型的预测结果,使用sess.run
result = sess.run(y_pred, feed_dict=feed_dict_testing)
# 根据预测得分,获得最大值的标签索引做为标签索引,获得最终的预测结果
res_label = ['cat', 'dog']
print(res_label[result.argmax()])

深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)

上一篇:Linux--Tail命令


下一篇:iptables-qos-tcpcopy-tc-tcpdump