机器学习:TensorFlow 简例
2020-04-08 本文已影响0人
moon_light_
# -*- coding:utf-8 -*-
import tensorflow as tf
'''
出现以下 Warning
Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX
原因
tensorflow 觉得你电脑 cpu 还行,支持 AVX(Advanced Vector Extensions),运算速度还可以提升,所以可以开启更好更快的模式
解决方案
Just disables the warning, doesn’t enable AVX/FMA
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
'''
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
'''
主要 3 种类型的张量
tf.constant
常数, 值不可改变, 会在图中创建节点, 不依赖于其他节点, 可被其他节点依赖
一般作为输入节点
tf.Variable
变量, 值可变, 会在图中创建节点, 可依赖其他节点, 也可被其他节点依赖, 需要初始化值
一般用于可训练的参数, 比如 w 和 b, 运行过程中(包括训练前和训练后), 这些值一直存在
tf.placeholder
占位符, 值不可改变, 不会在图中创建节点, 不需要初始化, 可在运行时再赋值
一般用于临时数据, 比如学习速度, 这个参数不需要在图中有节点表示, 而且训练结束后就不再使用, 又比如样本数据
Graph 图
有默认图,也可以自己创建图,张量都是在图里面创建的,不同的图可以有相同名字的张量
使用默认图创建张量
c = tf.Variable(tf.fill([2], 2.0))
自己创建图,并创建张量
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable("v", initializer=tf.zeros_initializer()(shape=[3]))
获取默认图
g = tf.get_default_graph()
运行 Session
通过会话 session 执行定义好的运算, session 拥有并管理 TensorFlow 运行时的所有资源
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
直接运行
sess = tf.Session()
print sess.run(result) ## 输出计算结果
print result.eval(session=sess) ## 结果一样
sess.close()
或
with tf.Session() as sess:
print sess.run(result)
print result.eval(session=sess)
设置默认会话
sess = tf.Session()
with sess.as_default():
print result.eval()
或
sess = tf.InteractiveSession()
print result.eval()
sess.close()
session 使用默认图,也可以自己指定图
sess = tf.Session(graph=g1)
变量管理
## 下面两个定义等价
## 区别: Variable 的 name 是可选的, 而 get_variable 是必须指定的
## get_variable 如果发现已有同名变量存在, 会报错, 而 Variable 不会
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0, shape=[1]), name="v")
## 在名字为 foo 的空间内创建 v 变量, 如果该空间已存在 v 变量则报错
with tf.variable_scope("foo"):
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
## 将 reuse 设为 True, 这样 get_variable 只获取已经创建过的变量, 如果变量不存在则报错
with tf.variable_scope("foo", reuse=True):
v1 = tf.get_variable("v", [1])
print v == v1
## 使用变量管理的一个好处是不用在函数间传递大量参数
初始化变量
需要初始化所有的 Variable
tf.global_variables_initializer().run(session=sess)
如果有指定默认 session 则
tf.global_variables_initializer().run()
旧函数
tf.initialize_all_variables()
'''
sess = tf.Session()
hello = tf.constant('Hello, TensorFlow!')
print sess.run(hello)
a = tf.constant(10)
b = tf.constant(32)
print sess.run(a + b)
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
print result ## 显示 Tensor("add_1:0", shape=(2,), dtype=float32)
print sess.run(result) ## 显示 [3. 5.]
c = tf.Variable(tf.fill([2], 2.0)) ## diff with tf.fill([1, 2], 2.0)
d = tf.Variable(tf.fill([1,2], 2.0))
tf.global_variables_initializer().run(session=sess) ## need to init all var
print sess.run(result - c)
print sess.run(result - d)
print a.graph is tf.get_default_graph() ## 获取张量 a 所在的 graph, 并判断其是否默认图
sess.close()
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable("v", initializer=tf.zeros_initializer()(shape=[3]))
g2 = tf.Graph()
with g2.as_default():
v = tf.get_variable("v", initializer=tf.ones_initializer()(shape=[3]))
with tf.Session(graph=g1) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print sess.run(tf.get_variable("v"))
with tf.Session(graph=g2) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print tf.get_variable("v").eval() ## 似乎 with 语句自动把 sess 设为默认会话所以可以直接使用 eval()
sess = tf.InteractiveSession()
x = tf.Variable(tf.random_normal([5,3]))
w = tf.Variable(tf.random_normal([3,2]))
b = tf.Variable(tf.fill([1,2], 0.5))
y = tf.matmul(x,w) + b
tf.global_variables_initializer().run()
print y.eval()
sess.close()
'''
w = tf.Variable(tf.fill([2,3], 3.0)) ## 产生全 3 的 2*3 矩阵作为变量
w2 = tf.Variable(w.initialized_value())
w3 = tf.Variable(w.initialized_value()*2) ## 用其他变量来初始化新的变量
w5 = w2.assign(w3) ## 将 w3 赋给 w2, 运行 w5 后才生效
'''
'''
## 指定计算设备
g = tf.Graph()
with g.device('/gpu:0'):
result = a + b
'''
'''
## 通过集合管理不同资源如张量, 变量, 队列资源等
tf.add_to_collection
tf.get_collection
'''
############
## 神经网络
############
from numpy.random import RandomState
batch_size = 8 ## 训练数据 batch 的大小
## 定义权值
## w1 是输入层和隐藏层之间的权值
## w2 是隐藏层和输出层之间的权值
## 输入有 2 个特征
## 隐藏层有 3 个节点
## 输出层有 1 个节点
w1 = tf.Variable(tf.random_normal([2,3], stddev=1))
## tf.random_normal([3,1], stddev=1) 产生 3*1 矩阵, 元素是均值为 0, 标准差为 1 的随机数
## 如果加上 seed=1 会导致每次的随机数一样
w2 = tf.Variable(tf.random_normal([3,1], stddev=1))
## 偏移值, 产生全为 0.5 的 1*3 矩阵作为变量
b1 = tf.Variable(tf.fill([3], 0.5))
b2 = tf.Variable(tf.fill([1], 0.5))
## 定义输入
## 由于输入是常量表示, 如果每轮迭代选取的数据都要通过常量来表示, 那么 TensorFlow 的计算图将会太大
## 为避免这个问题, TensorFlow 提供了 placeholder
## placeholder 相当于定义了一个位置, 这个位置中的数据在程序运行时再指定, 所以不会产生太多的图
x = tf.placeholder(tf.float32, shape=(None, 2), name='x-input')
## 赋值的时候可以自动判断 shape
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')
## 定义神经网络前向传播, 假设激活函数是 f(x) = x
a = tf.matmul(x, w1) + b1
y = tf.matmul(a, w2) + b2
## 定义损失函数(交叉熵)
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
## 定义反向传播
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
## 随机生成有两个特征值的输入数据
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
Y = [[int(x1+x2<1)] for (x1,x2) in X]
print "X=\n" + str(X)
print "Y=\n" + str(Y)
with tf.Session() as sess:
tf.global_variables_initializer().run() ## 一次性初始化所有变量
print "\n"
print sess.run(w1) ## 训练之前神经网络的参数值
print sess.run(w2)
print sess.run(b1)
print sess.run(b2)
print "\n"
STEPS = 5000 ## 迭代次数
for i in range(STEPS):
start = (i*batch_size) % dataset_size
end = min(start+batch_size, dataset_size)
sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
if i % 1000 == 0:
total_cross_entropy = sess.run(cross_entropy, feed_dict={x:X, y_:Y})
## 隔一段时间计算所有数据的交叉熵输出, 理想情况是最终变成 0, 但有时似乎不行
print("after " + str(i) + " training step(s), cross entropy on all data is " + str(total_cross_entropy))
print "\n"
print sess.run(w1) ## 训练之后神经网络的参数值
print sess.run(w2)
print sess.run(b1)
print sess.run(b2)
print "\n"
result = sess.run(y, feed_dict={x: X})
print result
print result - Y