# coding=utf-8
# 数据集形式:
# ./dataset:
# train:
# cat:
# cat_001
# cat_002
# cat_003
# .
# .
# .
# .
# .
# .
# dog:
# dog_001
# dog_002
# dog_003
# .
# .
# .
# .
# .
# .
# 两部分: 一:数据读取部分 二:搭建网络
#padding(参数为'SAME'时需要paddding) 存在的意义在于
# 为了不丢弃原图信息
# 为了保持feature map 的大小与原图一致
# 为了让更深层的layer的input依旧保持有足够大的信息量
# 为了实现上述目的,且不做多余的事情,padding出来的pixel的值都是0,不存在噪音问题
# padding = (卷积核大小 - stride) / 2
# featuremap长与宽的计算公式:(inputsize - 卷积核大小 + 2 * padding) / stride + 1
import os
import cv2
import tensorflow as tf
import random
import glob
import numpy as np
class_num = 2
lr = 0.01
epochs = 1000
batchsize = 64
imgsize = 128
datadir = 'D:/lizhenqi/catanddog/train'
classification = ['cat',
'dog']
class DataSet:
def __init__(self,path,classification):
self.path = path
self.classification = classification
#@staticmethod
def get_imgdataandlabel(self):
img_data = []
img_labels = []
idx = 0 # 标签
for classname in self.classification:
img_list = glob.glob(os.path.join(self.path,classname) + '/*')
img_label = [idx for i in range(len(img_list))]
img_data += img_list
img_labels += img_label
idx += 1
return img_data, img_labels
path = datadir
dataset = DataSet(path,classification)
img_data, imglabels = dataset.get_imgdataandlabel()
print(imglabels)
imgs = []
for img in img_data:
data = cv2.imread(img)
data = cv2.resize(data,(imgsize,imgsize))
imgs.append(data)
# 编码标签(2类)
labels = []
for l in imglabels:
label = np.zeros([2])
label[l] = 1
# print(label)
labels.append(label)
print(len(imgs),len(labels))
print(labels)
indexs = [i for i in range(len(imgs))]
#print(indexs,len(labels))
random.shuffle(indexs)
inputs = []
true_labels = []
for index in indexs:
inputs.append(imgs[index])
true_labels.append(labels[index])
#print(inputs)
inputs = inputs*epochs
true_labels = labels*epochs
print(inputs[0:1])
#print(true_labels)
x = tf.placeholder(tf.float32,[batchsize,128,128,3],'x')
y = tf.placeholder(tf.float32,[batchsize,class_num],'y')
#定义卷积核 shape(height,wide,输入channels,输出channels)
def weight_variable(shape):
return tf.Variable(tf.truncated_normal(shape,stddev=0.1))
#定义偏置 shape(输出channels)
def bias_variable(shape):
return tf.Variable(tf.constant(0.1,shape=shape))
def conv2d(x,W):
return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME') #实现了滑动窗口的滤波
def max_pool_2x2(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
def loss(labels,logits):
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=logits))
return cross_entropy
def optimizer1(loss,lr):
train_op = tf.train.GradientDescentOptimizer(lr).minimize(loss) # Add Ops to the graph to minimize a cost by updating a list of variables,you can get gradients,variables_new
return train_op
def optimizer2(loss,lr):
train_op = tf.train.AdamOptimizer(lr).minimizer(loss)
#定义三层卷积网络 ,假设输入的是shape(batchsize,128,128,3)的图片
def simplenet(inputs,class_num,istrain=True):
with tf.variable_scope('conv1'):
W_conv1 = weight_variable([5,5,3,32])
b_conv1 = bias_variable([32]) #大小和输出通道数一致
net = conv2d(inputs,W_conv1) + b_conv1 #:大小:128-5+2*2/1+1=128 其实不用算,padding目的就是维持大小和输入一致
net = tf.nn.relu(net)
net = max_pool_2x2(net) # shape(batchsize,64,64,32)
with tf.variable_scope('conv2'):
W_conv2 = weight_variable([3,3,32,64])
b_conv2 = bias_variable([64])
net = conv2d(net,W_conv2) + b_conv2
net = tf.nn.relu(net)
net = max_pool_2x2(net) # shape(batchsize,32,32,64)
with tf.variable_scope('conv3'):
W_conv3 = weight_variable([3,3,64,128])
b_conv3 = bias_variable([128])
net = conv2d(net,W_conv3) + b_conv3
net = tf.nn.relu(net)
net = max_pool_2x2(net) # shape(batchsize,16,16,128)
net_flat = tf.reshape(net,[batchsize,16*16*128])
with tf.variable_scope('fc'):
w_fc1 = weight_variable([16*16*128,class_num])
b_fc1 = bias_variable([class_num])
logits = tf.nn.relu(tf.matmul(net_flat,w_fc1) + b_fc1) # shape(batchsize,class_num)
return logits
logits = simplenet(x,class_num)
loss = loss(y,logits)
train_op = optimizer1(loss,lr)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
steps = epochs * len(img_data) // batchsize
for step in range(steps):
batch_inputs = inputs[step*batchsize:(step+1)*batchsize]
batch_labels = true_labels[step*batchsize:(step+1)*batchsize]
los, _ = sess.run([loss,train_op],feed_dict={x:batch_inputs,y:batch_labels})
if step%100 == 0:
print(step,' step: ',' loss is ',los)
优化器 :
基类:tf.train.optimizer()
基类下面的方法:
minimize(cost,<list of variables) ,返回一个节点,会更新当前step的gradients,variables,lost
compute_gradients(loss, <list of variables),# return grads_and_vars, grads_and_vars is a list of tuples (gradient, variable). Do whatever you need to the ‘gradient’ part, for example cap them, etc
apply_gradients(grads_and_vars),# Ask the optimizer to apply the capped gradients.
子类:class tf.train.GradientDescentOptimizer
class tf.train.AdagradOptimizer
class tf.train.MomentumOptimizer
class tf.train.AdamOptimizer
class tf.train.FtrlOptimizer
class tf.train.RMSPropOptimizer
注:tf.train.Optimizer.minimize() 返回的是节点,不返回var_list,返回operation.