注意:此代码全部为TensorFlow1版本。

查看Tensorflow版本

1
2
3
4
5
6
7
8
9
10
11
from __future__ import absolute_import, division, print_function, unicode_literals

# 导入TensorFlow和tf.keras
import tensorflow as tf
from tensorflow import keras

# 导入辅助库
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)

Helloworld程序

1
2
3
4
5
6
7
# tf的helloworld程序
import tensorflow as tf

hello = tf.constant('Hello, world!') # 定义一个常量
sess = tf.Session() # 创建一个session
print(sess.run(hello)) # 计算
sess.close()

张量相加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 常量加法运算示例
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别

a = tf.constant(5.0) # 定义常量a
b = tf.constant(1.0) # 定义常量a
c = tf.add(a, b)
print("c:", c)

graph = tf.get_default_graph() # 获取缺省图
print(graph)

with tf.Session() as sess:
print(sess.run(c)) # 执行计算

查看图对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 常量加法运算示例
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别

a = tf.constant(5.0) # 定义常量a
b = tf.constant(1.0) # 定义常量a
c = tf.add(a, b)
print("c:", c)

graph = tf.get_default_graph() # 获取缺省图
print(graph)

with tf.Session() as sess:
print(sess.run(c)) # 执行计算
print(a.graph) # 通过tensor获取graph对象
print(c.graph) # 通过op获取graph对象
print(sess.graph) # 通过session获取graph对象

指定执行某个图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建多个图,指定图运行
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别

a = tf.constant(5.0) # 定义常量a
b = tf.constant(1.0) # 定义常量b
c = tf.add(a, b)

graph = tf.get_default_graph() # 获取缺省图
print(graph)

graph2 = tf.Graph()
print(graph2)
with graph2.as_default(): # 在指定图上创建op
d = tf.constant(11.0)

with tf.Session(graph=graph2) as sess:
print(sess.run(d)) # 执行计算
# print(sess.run(c)) # 报错

查看张量属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建多个图,指定图运行
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 调整警告级别

# a = tf.constant(5.0) # 定义常量a
# a = tf.constant([1,2,3])
a = tf.constant([[1,2,3],[4,5,6]])

with tf.Session() as sess:
print(sess.run(a)) # 执行计算
print("name:", a.name)
print("dtype:", a.dtype)
print("shape:", a.shape)
print("op:", a.op)
print("graph:", a.graph)

生成张量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建张量操作
import tensorflow as tf

# 生成值全为0的张量
tensor_zeros = tf.zeros(shape=[2, 3], dtype="float32")
# 生成值全为1的张量
tensor_ones = tf.ones(shape=[2, 3], dtype="float32")
# 创建正态分布张量
tensor_nd = tf.random_normal(shape=[10],
mean=1.7,
stddev=0.2,
dtype="float32")
# 生成和输入张量形状一样的张量,值全为1
tensor_zeros_like = tf.zeros_like(tensor_ones)

with tf.Session() as sess:
print(tensor_zeros.eval()) # eval表示在session中计算该张量
print(tensor_ones.eval())
print(tensor_nd.eval())
print(tensor_zeros_like.eval())

张量类型转换

1
2
3
4
5
6
7
8
9
# 张量类型转换
import tensorflow as tf

tensor_ones = tf.ones(shape=[2, 3], dtype="int32")
tensor_float = tf.constant([1.1, 2.2, 3.3])

with tf.Session() as sess:
print(tf.cast(tensor_ones, tf.float32).eval())
# print(tf.cast(tensor_float, tf.string).eval()) #不支持浮点数到字符串直接转换

占位符使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 占位符示例
import tensorflow as tf

# 不确定数据,先使用占位符占个位置
plhd = tf.placeholder(tf.float32, [2, 3]) # 2行3列的tensor
plhd2 = tf.placeholder(tf.float32, [None, 3]) # N行3列的tensor

with tf.Session() as sess:
d = [[1, 2, 3],
[4, 5, 6]]
print(sess.run(plhd, feed_dict={plhd: d}))
print("shape:", plhd.shape)
print("name:", plhd.name)
print("graph:", plhd.graph)
print("op:", plhd.op)
print(sess.run(plhd2, feed_dict={plhd2: d}))

改变张量形状

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 改变张量形状示例(重点)
import tensorflow as tf

pld = tf.placeholder(tf.float32, [None, 3])
print(pld)

pld.set_shape([4, 3])
print(pld)
# pld.set_shape([3, 3]) #报错,静态形状一旦固定就不能再设置静态形状

# 动态形状可以创建一个新的张量,改变时候一定要注意元素的数量要匹配
new_pld = tf.reshape(pld, [3, 4])
print(new_pld)
# new_pld = tf.reshape(pld, [2, 4]) # 报错,元素的数量不匹配

with tf.Session() as sess:
pass

数学计算

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
# 数学计算示例
import tensorflow as tf

x = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
y = tf.constant([[4, 3], [3, 2]], dtype=tf.float32)

x_add_y = tf.add(x, y) # 张量相加
x_mul_y = tf.matmul(x, y) # 张量相乘
log_x = tf.log(x) # log(x)

# reduce_sum: 此函数计算一个张量的各个维度上元素的总和
x_sum_1 = tf.reduce_sum(x, axis=[1]) #0-列方向 1-行方向

# segment_sum: 沿张量的片段计算总和
# 函数返回的是一个Tensor,它与data有相同的类型,与data具有相同的形状
# 但大小为 k(段的数目)的维度0除外
data = tf.constant([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=tf.float32)
segment_ids = tf.constant([0, 0, 0, 1, 1, 2, 2, 2, 2, 2], dtype=tf.int32)
x_seg_sum = tf.segment_sum(data, segment_ids) # [6, 9, 40]

with tf.Session() as sess:
print(x_add_y.eval())
print(x_mul_y.eval())
print(log_x.eval())
print(x_sum_1.eval())
print(x_seg_sum.eval())

变量使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 变量OP示例
import tensorflow as tf
# 创建普通张量
a = tf.constant([1, 2, 3, 4, 5])
# 创建变量
var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0),
name="variable")

# 变量必须显式初始化, 这里定义的是初始化操作,并没有运行
init_op = tf.global_variables_initializer()

with tf.Session() as sess:
sess.run(init_op)
print(sess.run([a, var]))

可视化

第一步:编写代码

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
# 变量OP示例
import tensorflow as tf

''' 变量OP
1. 变量OP能够持久化保存,普通张量则不可
2. 当定义一个变量OP时,在会话中进行初始化
3. name参数:在tensorboard使用的时候显示名字,可以让相同的OP进行区分
'''

# 创建普通张量
a = tf.constant([1, 2, 3, 4, 5])
# 创建变量
var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0),
name="variable")

b = tf.constant(3.0, name="a")
c = tf.constant(4.0, name="b")
d = tf.add(b, c, name="add")

# 变量必须显式初始化, 这里定义的是初始化操作,并没有运行
init_op = tf.global_variables_initializer()

with tf.Session() as sess:
sess.run(init_op)
# 将程序图结构写入事件文件
fw = tf.summary.FileWriter("../summary/", graph=sess.graph)
print(sess.run([a, var]))

第二步:启动tensorborad

1
tensorboard  --logdir="PycharmProjects/tensorflow_study/summary/"

第三步:访问tensorborad主页

1
http://127.0.0.1:6006

实现线性回归

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
# 线性回归示例
import tensorflow as tf

# 第一步:创建数据
x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name="x_data")
y_true = tf.matmul(x, [[2.0]]) + 5.0 # 矩阵相乘必须是二维的

# 第二步:建立线性回归模型
# 建立模型时,随机建立权重、偏置 y = wx + b
# 权重需要不断更新,所以必须是变量类型. trainable指定该变量是否能随梯度下降一起变化
weight = tf.Variable(tf.random_normal([1, 1], name="w"),
trainable=True) # 训练过程中值是否允许变化
bias = tf.Variable(0.0, name="b", trainable=True) # 偏置
y_predict = tf.matmul(x, weight) + bias # 计算 wx + b

# # 第三步:求损失函数,误差(均方差)
loss = tf.reduce_mean(tf.square(y_true - y_predict))

# # 第四步:使用梯度下降法优化损失
# 学习率是比价敏感的参数,过小会导致收敛慢,过大可能导致梯度爆炸
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

### 收集损失值
tf.summary.scalar("losses", loss)
merged = tf.summary.merge_all() #将所有的摘要信息保存到磁盘

init_op = tf.global_variables_initializer()
with tf.Session() as sess: # 通过Session运行op
sess.run(init_op)
# 打印初始权重、偏移值
print("weight:", weight.eval(), " bias:", bias.eval())

### 指定事件文件
fw = tf.summary.FileWriter("../summary/", graph=sess.graph)

for i in range(500): # 循环执行训练
sess.run(train_op) # 执行训练
summary = sess.run(merged) ### 运行合并摘要op
fw.add_summary(summary, i) ### 写入文件
print(i, ":", i, "weight:", weight.eval(), " bias:", bias.eval())

模型保存与加载

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
# 模型保存示例
import tensorflow as tf
import os

# 第一步:创建数据
x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name="x_data")
y_true = tf.matmul(x, [[2.0]]) + 5.0 # 矩阵相乘必须是二维的

# 第二步:建立线性回归模型
# 建立模型时,随机建立权重、偏置 y = wx + b
# 权重需要不断更新,所以必须是变量类型. trainable指定该变量是否能随梯度下降一起变化
weight = tf.Variable(tf.random_normal([1, 1], name="w"),
trainable=True) # 训练过程中值是否允许变化
bias = tf.Variable(0.0, name="b", trainable=True) # 偏置
y_predict = tf.matmul(x, weight) + bias # 计算 wx + b

# # 第三步:求损失函数,误差(均方差)
loss = tf.reduce_mean(tf.square(y_true - y_predict))

# # 第四步:使用梯度下降法优化损失
# 学习率是比价敏感的参数,过小会导致收敛慢,过大可能导致梯度爆炸
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

# 收集损失值
tf.summary.scalar("losses", loss)
merged = tf.summary.merge_all() #将所有的摘要信息保存到磁盘

init_op = tf.global_variables_initializer()

saver = tf.train.Saver() #实例化Saver
with tf.Session() as sess: # 通过Session运行op
sess.run(init_op)
print("weight:", weight.eval(), " bias:", bias.eval()) # 打印初始权重、偏移值
fw = tf.summary.FileWriter("../summary/", graph=sess.graph) # 指定事件文件
# 训练之前,加载之前训练的模型,覆盖之前的参数
if os.path.exists("../model/linear_model/checkpoint"):
saver.restore(sess, "../model/linear_model/")

for i in range(500): # 循环执行训练
sess.run(train_op) # 执行训练
summary = sess.run(merged) # 运行合并后的tensor
fw.add_summary(summary, i)
print(i, ":", i, "weight:", weight.eval(), " bias:", bias.eval())

saver.save(sess, "../model/linear_model/")

CSV样本读取

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
# csv文件读取示例
import tensorflow as tf
import os
def csv_read(filelist):
# 构建文件队列
file_queue = tf.train.string_input_producer(filelist)
# 构建csv reader,读取队列内容(一行)
reader = tf.TextLineReader()
k, v = reader.read(file_queue)
# 对每行内容进行解码
## record_defaults:指定每一个样本每一列的类型,指定默认值
records = [["None"], ["None"]]
example, label = tf.decode_csv(v, record_defaults=records) # 每行两个值
# 批处理
# batch_size: 跟队列大小无关,只决定本批次取多少数据
example_bat, label_bat = tf.train.batch([example, label],
batch_size=9,
num_threads=1,
capacity=9)
return example_bat, label_bat


if __name__ == "__main__":
# 找到文件,构造一个列表
dir_name = "./test_data/"
file_names = os.listdir(dir_name)
file_list = []
for f in file_names:
file_list.append(os.path.join(dir_name, f)) # 拼接目录和文件名

example, label = csv_read(file_list)
# 开启session运行结果
with tf.Session() as sess:
coord = tf.train.Coordinator() # 定义线程协调器
# 开启读取文件线程
# 调用 tf.train.start_queue_runners 之后,才会真正把tensor推入内存序列中
# 供计算单元调用,否则会由于内存序列为空,数据流图会处于一直等待状态
# 返回一组线程
threads = tf.train.start_queue_runners(sess, coord=coord)
print(sess.run([example, label])) # 打印读取的内容
# 回收线程
coord.request_stop()
coord.join(threads)

图像样本读取

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
# 图片文件读取示例
import tensorflow as tf
import os

def img_read(filelist):
# 构建文件队列
file_queue = tf.train.string_input_producer(filelist)
# 构建reader读取文件内容,默认读取一张图片
reader = tf.WholeFileReader()
k, v = reader.read(file_queue)

# 对图片数据进行解码
img = tf.image.decode_jpeg(v)

# 批处理, 图片需要处理成统一大小
img_resized = tf.image.resize(img, [200, 200]) # 200*200
img_resized.set_shape([200, 200, 3]) # 固定样本形状,批处理时对数据形状有要求
img_bat = tf.train.batch([img_resized],
batch_size=10,
num_threads=1)
return img_bat


if __name__ == "__main__":
# 找到文件,构造一个列表
dir_name = "../data/test_img/"
file_names = os.listdir(dir_name)
file_list = []
for f in file_names:
file_list.append(os.path.join(dir_name, f)) # 拼接目录和文件名
imgs = img_read(file_list)
# 开启session运行结果
with tf.Session() as sess:
coord = tf.train.Coordinator() # 定义线程协调器
# 开启读取文件线程
# 调用 tf.train.start_queue_runners 之后,才会真正把tensor推入内存序列中
# 供计算单元调用,否则会由于内存序列为空,数据流图会处于一直等待状态
# 返回一组线程
threads = tf.train.start_queue_runners(sess, coord=coord)
# print(sess.run([imgs])) # 打印读取的内容
imgs = imgs.eval()

# 回收线程
coord.request_stop()
coord.join(threads)

## 显示图片
print(imgs.shape)
import matplotlib.pyplot as plt

plt.figure("Img Show", facecolor="lightgray")

for i in range(10):
plt.subplot(2, 5, i+1)
plt.xticks([])
plt.yticks([])
plt.imshow(imgs[i].astype("int32"))

plt.tight_layout()
plt.show()

实现手写体识别

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 手写体识别
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import pylab

# 读入数据集(如果没有则在线下载),并转换成独热编码
# 如果不能下载,则到http://yann.lecun.com/exdb/mnist/进行手工下载,下载后拷贝到当前MNIST_data目录下
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder(tf.float32, [None, 784]) # 占位符,输入
y = tf.placeholder(tf.float32, [None, 10]) # 占位符,输出

W = tf.Variable(tf.random_normal([784, 10])) # 权重
b = tf.Variable(tf.zeros([10])) # 偏置值

# 构建模型
pred_y = tf.nn.softmax(tf.matmul(x, W) + b) # softmax分类
print("pred_y.shape:", pred_y.shape)
# 损失函数
cross_entropy = -tf.reduce_sum(y * tf.log(pred_y),
reduction_indices=1) # 求交叉熵
cost = tf.reduce_mean(cross_entropy) # 求损失函数平均值

# 参数设置
lr = 0.01
# 梯度下降优化器
optimizer = tf.train.GradientDescentOptimizer(lr).minimize(cost)

training_epochs = 200
batch_size = 100
saver = tf.train.Saver()
model_path = "../model/mnist/mnist_model.ckpt" # 模型路径

# 启动session
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 循环开始训练
for epoch in range(training_epochs):
avg_cost = 0.0
total_batch = int(mnist.train.num_examples / batch_size) # 计算总批次

# 遍历全数据集
for i in range(total_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size) # 读取一个批次样本
params = {x: batch_xs, y: batch_ys} # 训练参数

o, c = sess.run([optimizer, cost], feed_dict=params) # 执行训练

avg_cost += (c / total_batch) # 求平均损失值

print("epoch: %d, cost=%.9f" % (epoch + 1, avg_cost))

print("Finished!")

# 模型评估
correct_pred = tf.equal(tf.argmax(pred_y, 1), tf.argmax(y, 1))
# 计算准确率
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
print("accuracy:", accuracy.eval({x: mnist.test.images,
y: mnist.test.labels}))
# 将模型保存到文件
save_path = saver.save(sess, model_path)
print("Model saved:", save_path)

# 测试模型
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver.restore(sess, model_path) # 加载模型

batch_xs, batch_ys = mnist.test.next_batch(2) # 读取2个测试样本
output = tf.argmax(pred_y, 1) # 预测结果值

output_val, predv = sess.run([output, pred_y], # 操作
feed_dict={x: batch_xs}) # 参数

print("预测结论:\n", output_val, "\n")
print("实际结果:\n", batch_ys, "\n")
print("预测概率:\n", predv, "\n")

# 显示图片
im = batch_xs[0] # 第1个测试样本数据
im = im.reshape(28, 28)
pylab.imshow(im)
pylab.show()

im = batch_xs[1] # 第2个测试样本数据
im = im.reshape(28, 28)
pylab.imshow(im)
pylab.show()

利用CNN实现服饰识别

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# 在fashion_mnist数据集实现服饰识别
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets

class FashionMnist():
out_featrues1 = 12 # 第一个组卷积池化层输出特征数量(等于第一个卷积层卷积核数量)
out_featrues2 = 24 # 第二个组卷积池化层输出特征数量(等于第二个卷积层卷积核数量)
con_neurons = 512 # 全连接层神经元数量

def __init__(self, path):
"""
构造方法
:param path:指定数据集路径
:return:
"""
self.sess = tf.Session() # 会话
self.data = read_data_sets(path, one_hot=True) # 读取样本文件对象

def init_weight_variable(self, shape):
"""
初始化权重方法
:param shape:指定初始化张量的形状
:return:经过初始化后的张量
"""
inital = tf.truncated_normal(shape, stddev=0.1) # 截尾正态分布
return tf.Variable(inital)

def init_bias_variable(self, shape):
"""
初始化偏置
:param shape:指定初始化张量的形状
:return:经过初始化后的张量
"""
inital = tf.constant(1.0, shape=shape)
return tf.Variable(inital)

def conv2d(self, x, w):
"""
二维卷积方法
:param x:原始数据
:param w:卷积核
:return:返回卷积后的结果
"""
# input : 输入数据[batch, in_height, in_width, in_channels]
# filter : 卷积窗口[filter_height, filter_width, in_channels, out_channels]
# strides: 卷积核每次移动步数,对应着输入的维度方向
# padding='SAME' : 输入和输出的张量形状相同
return tf.nn.conv2d(x, # 原始数据
w, # 卷积核
strides=[1, 1, 1, 1], # 各个维度上的步长值
padding="SAME") # 输入和输出矩阵大小相同

def max_pool_2x2(self, x):
"""
池化函数
:param x:原始数据
:return:池化后的数据
"""
return tf.nn.max_pool(x,# 原始数据
ksize=[1, 2, 2, 1], # 池化区域大小
strides=[1, 2, 2, 1], # 各个维度上的步长值
padding="SAME")

def create_conv_pool_layer(self, input, input_features, out_features):
"""
卷积、激活、池化层
:param input:原始数据
:param input_features:输入特征数量
:param out_features:输出特征数量
:return:卷积、激活、池化层后的数据
"""
filter = self.init_weight_variable([5, 5, input_features, out_features])#卷积核
b_conv = self.init_bias_variable([out_features]) # 偏置,数量和卷积输出大小一致

h_conv = tf.nn.relu(self.conv2d(input, filter) + b_conv)#卷积,结果做relu激活
h_pool = self.max_pool_2x2(h_conv) #对激活操作输出做max池化
return h_pool

def create_fc_layer(self, h_pool_flat, input_featrues, con_neurons):
"""
创建全连接层
:param h_pool_flat:输入数据,经过拉伸后的一维张量
:param input_featrues:输入特征大小
:param con_neurons:神经元数量
:return:全连接
"""
w_fc = self.init_weight_variable([input_featrues, con_neurons])#输出数量等于神经元数量
b_fc = self.init_bias_variable([con_neurons]) #偏置数量等于输出数量
h_fc1 = tf.nn.relu(tf.matmul(h_pool_flat, w_fc) + b_fc) #计算wx+b并且做relu激活
return h_fc1

def build(self):
"""
组建CNN
:return:
"""
# 输入数据,N个28*28经过拉伸后的张量
self.x = tf.placeholder(tf.float32, shape=[None, 784])
x_image = tf.reshape(self.x, [-1, 28, 28, 1]) # 28*28单通道
self.y_ = tf.placeholder(tf.float32, shape=[None, 10]) # 标签,对应10个类别
# 第一组卷积池化层
h_pool1 = self.create_conv_pool_layer(x_image, 1, self.out_featrues1)
# 第二组卷积池化层
h_pool2 = self.create_conv_pool_layer(h_pool1, # 上一层输出作为输入
self.out_featrues1, # 上一层输出特征数量作为输入特征数量
self.out_featrues2)# 第二层输出特征数量
# 全连接层
h_pool2_flat_features = 7 * 7 * self.out_featrues2 # 计算特征点数量
h_pool2_flat = tf.reshape(h_pool2, [-1, h_pool2_flat_features])#拉升成一维张量
h_fc = self.create_fc_layer(h_pool2_flat, # 输入
h_pool2_flat_features, # 输入特征数量
self.con_neurons) # 输出特征数量
# dropout层(通过随机丢弃一部分神经元的更新,防止过拟合)
self.keep_prob = tf.placeholder("float") # 丢弃率
h_fc1_drop = tf.nn.dropout(h_fc, self.keep_prob)
# 输出层
w_fc = self.init_weight_variable([self.con_neurons, 10])#512行10列,产生10个输出
b_fc = self.init_bias_variable([10]) # 10个偏置
y_conv = tf.matmul(h_fc1_drop, w_fc) + b_fc # 计算wx+b, 预测结果

# 评价
correct_prediction = tf.equal(tf.argmax(y_conv, 1),#取出预测概率中最大的值的索引
tf.argmax(self.y_, 1))#取出真实概率中最大的值的索引
# 将上一步得到的bool类型数组转换为浮点型,并求准确率
self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 损失函数
loss_func = tf.nn.softmax_cross_entropy_with_logits(labels=self.y_,#真实值
logits=y_conv)#预测值
cross_entropy = tf.reduce_mean(loss_func)
# 优化器
optimizer = tf.train.AdamOptimizer(0.001)
self.train_step = optimizer.minimize(cross_entropy)

def train(self):
self.sess.run(tf.global_variables_initializer()) #初始化
merged = tf.summary.merge_all() #摘要合并

batch_size = 100
print("beging training...")

for i in range(10): # 迭代训练
total_batch = int(self.data.train.num_examples / batch_size)#计算批次数量

for j in range(total_batch):
batch = self.data.train.next_batch(batch_size)#获取一个批次样本
params = {self.x: batch[0], self.y_:batch[1],#输入、标签
self.keep_prob: 0.5} #丢弃率

t, acc = self.sess.run([self.train_step, self.accuracy],# op
params) # 喂入参数
if j % 100 == 0:
print("epoch: %d, pass: %d, acc: %f" % (i, j, acc))
# 评价
def eval(self, x, y, keep_prob):
params = {self.x: x, self.y_: y, self.keep_prob: keep_prob}
test_acc = self.sess.run(self.accuracy, params)
print('Test accuracy %f' % test_acc)
return test_acc

# 关闭会话
def close(self):
self.sess.close()

if __name__ == "__main__":
mnist = FashionMnist('FASHION_MNIST_data/')
mnist.build()
mnist.train()

print('\n----- Test -----')
xs, ys = mnist.data.test.next_batch(100)
mnist.eval(xs, ys, 1.0)
mnist.close()