导入数据代码input_data.py
import os
import math
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
# ============================================================================
# -----------------生成图片路径和标签的List------------------------------------
# train_dir = 'E:/flower_world-master/input_data/train'
roses = []
label_roses = []
tulips = []
label_tulips = []
dandelion = []
label_dandelion = []
sunflowers = []
label_sunflowers = []
daisy=[]
label_daisy = []
# step1:获取所有的图片路径名,存放到
# 对应的列表中,同时贴上标签,存放到label列表中。
# def get_files(file_dir, ratio):
def get_files(file_dir):
for file in os.listdir(file_dir + '/roses'):
roses.append(file_dir + '/roses' + '/' + file)
label_roses.append(0)
for file in os.listdir(file_dir + '/tulips'):
tulips.append(file_dir + '/tulips' + '/' + file)
label_tulips.append(1)
for file in os.listdir(file_dir + '/dandelion'):
dandelion.append(file_dir + '/dandelion' + '/' + file)
label_dandelion.append(2)
for file in os.listdir(file_dir + '/sunflowers'):
sunflowers.append(file_dir + '/sunflowers' + '/' + file)
label_sunflowers.append(3)
for file in os.listdir(file_dir + '/daisy'):
daisy.append(file_dir + '/daisy' + '/' + file)
label_daisy.append(4)
# step2:对生成的图片路径和标签List做打乱处理
image_list = np.hstack((roses, tulips, dandelion, sunflowers, daisy))
label_list = np.hstack((label_roses, label_tulips, label_dandelion, label_sunflowers, label_daisy))
# 利用shuffle打乱顺序
temp = np.array([image_list, label_list])
temp = temp.transpose()
np.random.shuffle(temp)
# 将所有的img和lab转换成list
all_image_list = list(temp[:, 0])
all_label_list = list(temp[:, 1])
all_label_list = [int(i) for i in all_label_list]
return all_image_list, all_label_list
# ---------------------------------------------------------------------------
# --------------------生成Batch----------------------------------------------
# step1:将上面生成的List传入get_batch() ,转换类型,产生一个输入队列queue,因为img和lab
# 是分开的,所以使用tf.train.slice_input_producer(),然后用tf.read_file()从队列中读取图像
# image_W, image_H, :设置好固定的图像高度和宽度
# 设置batch_size:每个batch要放多少张图片
# capacity:一个队列最大多少
def get_batch(image, label, image_W, image_H, batch_size, capacity):
# 转换类型
image = tf.cast(image, tf.string)
label = tf.cast(label, tf.int32)
# make an input queue
input_queue = tf.train.slice_input_producer([image, label])
label = input_queue[1]
image_contents = tf.read_file(input_queue[0]) # read img from a queue
# step2:将图像解码,jpeg解码。
image = tf.image.decode_jpeg(image_contents, channels=3)
# step3:裁剪、归一化等操作,让计算出的模型更健壮。
#裁剪
image = tf.image.resize_image_with_crop_or_pad(image, image_W, image_H)
image = tf.image.per_image_standardization(image)
image_batch, label_batch = tf.train.batch([image, label],
batch_size=batch_size,
num_threads=32,
capacity=capacity)
# 重新排列label,行数为[batch_size]
label_batch = tf.reshape(label_batch, [batch_size])
image_batch = tf.cast(image_batch, tf.float32)
return image_batch, label_batch
模型代码model.py
import tensorflow as tf
def batch_norm_layer(value, is_training=False, name='batch_norm'):
'''
批量归一化 返回批量归一化的结果
args:
value:代表输入,第一个维度为batch_size
is_training:当它为True,代表是训练过程,这时会不断更新样本集的均值与方差。当测试时,要设置成False,这样就会使用训练样本集的均值和方差。
默认测试模式
name:名称。
'''
if is_training is True:
# 训练模式 使用指数加权函数不断更新均值和方差
return tf.contrib.layers.batch_norm(inputs=value, decay=0.9, updates_collections=None, is_training=True)
else:
# 测试模式 不更新均值和方差,直接使用
return tf.contrib.layers.batch_norm(inputs=value, decay=0.9, updates_collections=None, is_training=False)
# =========================================================================
# 网络结构定义
# 输入参数:images,image batch、4D tensor、tf.float32、[batch_size, width, height, channels]
# 返回参数:logits, float、 [batch_size, n_classes]
def inference(images, batch_size, n_classes,dropout_placeholdr,train ):
# def inference(images, batch_size, n_classes, dropout_placeholdr, train):
# 一个简单的卷积神经网络,卷积+池化层x2,全连接层x2,最后一个softmax层做分类。
# 卷积层1
# 64个3x3的卷积核(3通道),padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
with tf.variable_scope('conv1') as scope:
weights = tf.Variable(tf.truncated_normal(shape=[3, 3, 3, 64], stddev=1.0, dtype=tf.float32),
name='weights', dtype=tf.float32)
biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[64]),
name='biases', dtype=tf.float32)
conv = tf.nn.conv2d(images, weights, strides=[1, 1, 1, 1], padding='SAME')
pre_activation = tf.nn.bias_add(conv, biases)
# conv1 = tf.nn.relu(batch_norm_layer(pre_activation, train), name=scope.name)
conv1 = tf.nn.relu(pre_activation, name='conv1')
# 池化层1
# 3x3最大池化,步长strides为2,池化后执行lrn()操作,局部响应归一化,对训练有利。
with tf.variable_scope('pooling1_lrn') as scope:
pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pooling1')
norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
# 卷积层2
# 16个3x3的卷积核(16通道),padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
with tf.variable_scope('conv2') as scope:
weights = tf.Variable(tf.truncated_normal(shape=[3, 3, 64, 32], stddev=0.1, dtype=tf.float32),
name='weights', dtype=tf.float32)
biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[32]),
name='biases', dtype=tf.float32)
conv = tf.nn.conv2d(norm1, weights, strides=[1, 1, 1, 1], padding='SAME')
pre_activation = tf.nn.bias_add(conv, biases)
conv2 = tf.nn.relu(pre_activation, name='conv2')
# conv2 = tf.nn.relu(batch_norm_layer(pre_activation,train), name='conv2')
# 池化层3
# 3x3最大池化,步长strides为2,池化后执行lrn()操作,
# pool2 and norm2
with tf.variable_scope('pooling2_lrn') as scope:
pool2 = tf.nn.max_pool(conv2, ksize=[1, 3, 3, 1], strides=[1, 1, 1, 1], padding='SAME', name='pooling2')
norm2 = tf.nn.lrn(pool2, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm2')
# 卷积层3
# 16个3x3的卷积核(16通道),padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
with tf.variable_scope('conv3') as scope:
weights = tf.Variable(tf.truncated_normal(shape=[3, 3, 32, 16], stddev=0.1, dtype=tf.float32),
name='weights', dtype=tf.float32)
biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[16]),
name='biases', dtype=tf.float32)
conv = tf.nn.conv2d(norm2, weights, strides=[1, 1, 1, 1], padding='SAME')
pre_activation = tf.nn.bias_add(conv, biases)
conv3 = tf.nn.relu(pre_activation,name='conv3')
# conv3 = tf.nn.relu(batch_norm_layer(pre_activation,train), name='conv3')
# 池化层3
# 3x3最大池化,步长strides为2,池化后执行lrn()操作,
# pool3 and norm3
with tf.variable_scope('pooling2_lrn') as scope:
pool3 = tf.nn.max_pool(conv3, ksize=[1, 3, 3, 1], strides=[1, 1, 1, 1], padding='SAME', name='pooling2')
norm3 = tf.nn.lrn(pool3, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm2')
# 全连接层3
# 128个神经元,将之前pool层的输出reshape成一行,激活函数relu()
with tf.variable_scope('local3') as scope:
reshape = tf.reshape(norm3, shape=[batch_size, -1])
dim = reshape.get_shape()[1].value
weights = tf.Variable(tf.truncated_normal(shape=[dim, 128], stddev=0.005, dtype=tf.float32),
name='weights', dtype=tf.float32)
# weights = variable_with_weight_loss([dim, 128], stddev=0.04, wl=0.004)
biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[128]),
name='biases', dtype=tf.float32)
local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)
# 全连接层4
# 128个神经元,激活函数relu()
with tf.variable_scope('local4') as scope:
weights = tf.Variable(tf.truncated_normal(shape=[128, 128], stddev=0.005, dtype=tf.float32),
name='weights', dtype=tf.float32)
# weights = variable_with_weight_loss([128, 128], stddev=0.005, wl=0.004)
biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[128]),
name='biases', dtype=tf.float32)
local4 = tf.nn.relu(tf.matmul(local3, weights) + biases, name='local4')
# dropout层
with tf.variable_scope('dropout') as scope:
drop_out = tf.nn.dropout(local4, dropout_placeholdr)
# Softmax回归层
# 将前面的FC层输出,做一个线性回归,计算出每一类的得分
with tf.variable_scope('softmax_linear') as scope:
weights = tf.Variable(tf.truncated_normal(shape=[128, n_classes], stddev=0.005, dtype=tf.float32),
name='softmax_linear', dtype=tf.float32)
biases = tf.Variable(tf.constant(value=0.1, dtype=tf.float32, shape=[n_classes]),
name='biases', dtype=tf.float32)
softmax_linear = tf.add(tf.matmul(drop_out, weights), biases, name='softmax_linear')
# softmax_linear = tf.add(tf.matmul(local4, weights), biases, name='softmax_linear')
return softmax_linear
# -----------------------------------------------------------------------------
# loss计算
# 传入参数:logits,网络计算输出值。labels,真实值,0或者1
# 返回参数:loss,损失值
def losses(logits, labels):
with tf.variable_scope('loss') as scope:
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels,
name='xentropy_per_example')
loss = tf.reduce_mean(cross_entropy, name='loss')
tf.summary.scalar(scope.name + '/loss', loss)
return loss
# --------------------------------------------------------------------------
# loss损失值优化
# 输入参数:loss。learning_rate,学习速率。
# 返回参数:train_op,训练op,这个参数要输入sess.run中让模型去训练。
def trainning(loss, learning_rate):
with tf.name_scope('optimizer'):
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
return train_op
# -----------------------------------------------------------------------
# 评价/准确率计算
# 输入参数:logits,网络计算值。labels,标签,也就是真实值,在这里是0或者1。
# 返回参数:accuracy,当前step的平均准确率,也就是在这些batch中多少张图片被正确分类了。
def evaluation(logits, labels):
with tf.variable_scope('accuracy') as scope:
correct = tf.nn.in_top_k(logits, labels, 1)
correct = tf.cast(correct, tf.float16)
accuracy = tf.reduce_mean(correct)
tf.summary.scalar(scope.name + '/accuracy', accuracy)
return accuracy
这里面如果你不使用dropout层,则代码改成下面,把dropout层的代码注释掉
# softmax_linear = tf.add(tf.matmul(drop_out, weights), biases, name='softmax_linear')
softmax_linear = tf.add(tf.matmul(local4, weights), biases, name='softmax_linear')
如果你想使用BN层则每层的像下面那样的代码,注释第一条,使用第二条。
conv3 = tf.nn.relu(pre_activation,name='conv3')
conv3 = tf.nn.relu(batch_norm_layer(pre_activation,train), name='conv3')
模型的参数可以自己调节,我没有调节,用了源代码默认的。