介绍tensorflow
先主要介绍张量、图、常量与变量、占位符等基本概念
tensor 代表传递的数据为张量(也可以理解为多维数组),flow代表使用的是计算图。
简单的案例:
import tensorflow as tf
a = tf.constant(2,tf.int16)
b = tf.constant(4,tf.float32)
graph = tf.Graph()
with graph.as_default():
a = tf.Variable(8,tf.float32)
b = tf.Variable(tf.zeros([2,2],tf.float32))
with tf.Session(graph=graph) as session:
tf.global_variables_initializer().run()
print(session.run(a))
print(session.run(b))
这里打印出来的是下图的红色部分,而不是绿色部分。这是因为我们仅仅只是建了图,但是没有运行他
那该怎么办呢?给他一个会话。
import tensorflow as tf
a = tf.constant([1,2,3,4])
b = tf.constant([1,2,3,4])
result = a + b
graph = tf.Graph()
with graph.as_default():
a = tf.Variable(8,tf.float32)
b = tf.Variable(tf.zeros([2,2],tf.float32))
# with tf.Session(graph=graph) as session:
# tf.global_variables_initializer().run()
# print(session.run(a))
# print(session.run(b))
with tf.Session() as sess:
print(sess.run(result))
#输出[2,4,6,8]
常量,变量
tf.constant()
声明了常量
tf.Variable()
声明了变量
插针
#声明一个2行3列的变量矩阵,该变量的值服从标准差为1的正态分布,并随机生成
w1 = tf.Variable(tf.random_normal(shape=[2,3],stddev=1,seed=1))
此外还有tf.truncated_normal()
函数,是截断正态分布随机数,她只保留[mean-2strddev,mean+2stddev]。
因此,我们可以应用变量定义神经网络的权重矩阵和偏置项向量:
weight = tf.Variable(tf.truncated_normal([256*256,10]))
biases = tf.Variable(tf.zeros([10]))
#x.get_shape()返回的是元组shape,as_list()是将元组转为列表
print(weight.get_shape().as_list())
print(biases.get_shape().as_list())
#输出
[65536, 10]
[10]
占位符和feed_dict
占位符并没有初始值,它只会分配必要的内存。在会话中,占位符可以使用feed_dict
馈送数据。他是一个字典,在字典中需要给出每一占位符的取值。
在训练神经网络时需要每次提供一个批量的训练样本,如果每次迭代选取的数据要通过常量表示,那么 TensorFlow 的计算图会非常大。因为每增加一个常量,TensorFlow 都会在计算图中增加一个结点。所以说拥有几百万次迭代的神经网络会拥有极其庞大的计算图,而占位符却可以解决这一点,它只会拥有占位符这一个结点。
w1 = tf.Variable(tf.random_normal(shape=[2,3],stddev=1,seed=1))
weight = tf.Variable(tf.truncated_normal([256*256,10]))
# biases = tf.Variable(tf.zeros([10]))
# print(weight.get_shape().as_list())
# print(biases.get_shape().as_list())
w1 = tf.Variable(tf.random_normal([1,2],stddev=1))
#因为要重复输入x,而每建一个x就会生成一个节点,计算图的效率会减低,
#所以使用占位符
x=tf.placeholder(tf.float32,shape=(1,2))
x1=tf.constant([[0.7,0.9]])
a=x+w1
b=x1+w1
with tf.Session() as sess:
#先初始化
sess.run(tf.global_variables_initializer())
#运行y时将占位符填上,feed_dict为字典,变量名不可变
y_1=sess.run(a,feed_dict={x:[[0.7,0.9]]})
y2 = sess.run(b)
print(y_1)
print(y2)
#输出
[[-0.23070914 0.5880929 ]]
[[-0.23070914 0.5880929 ]]
其中 y_1
的计算过程使用占位符,而 y2
的计算过程使用常量。
尝试构建一段三层全连接神经网络的代码
import tensorflow as tf
#randomstate是产生随机状态种子
from numpy.random import RandomState
batch_size = 10
#w1隐藏层
w1 = tf.Variable(tf.random_normal([2,3],stddev = 1,seed=1))
w2 = tf.Variable(tf.random_normal([3,1],stddev= 1,seed =1))
#None可以根据batch大小确定维度,在shape的一个维度上使用None
#x是输入
x = tf.placeholder(tf.float32,shape=(None,2))
y = tf.placeholder(tf.float32,shape=(None,1))
#使用激活函数
a=tf.nn.relu(tf.matmul(x,w1))
# yhat = tf.nn.relu(tf.matmul(a,w2))
yhat=tf.nn.relu(tf.matmul(a,w2))
#定义交叉熵为损失函数,训练过程中使用Adma算法最小化交叉熵
cross_entropy = tf.reduce_mean(y*tf.log(tf.clip_by_value(yhat,1e-10,1.0)))
#根据纠缠熵来确定梯度下降的方向
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
#定义随机种子
rdm = RandomState(1)
data_size = 516
#生成两个特征,共data_size个样本
X = rdm.rand(data_size,2)
#定义规则给出的标签,所有x1+x2<1的样本认为是正样本,其他是负样本。Y,1为正样本
Y = [[int(x1+x2 < 1)] for (x1, x2) in X]
# print(tf.shape(Y))
# exit()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(w1))
print(sess.run(w2))
steps = 11000
for i in range(steps):
#选定每一个批量读取的首位位置,确保在1个epoch内采样训练
start = i*batch_size % data_size
# print(start)
# exit()
end = min(start+batch_size,data_size)
#梯度下降是分批的,也就是对每个批次的
sess.run(train_step, feed_dict={x:X[start:end],y:Y[start:end]})
if i%1000==0:
#损失函数是针对所有数据集
train_loss = sess.run(cross_entropy,feed_dict={x:X,y:Y})
print('在迭代%d次之后,训练损失为%g'%(i,train_loss))
上面的代码定义了一个简单的三层全连接网络(输入层、隐藏层和输出层分别为 2、3 和 1 个神经元),隐藏层和输出层的激活函数使用的是 ReLU 函数。该模型训练的样本总数为 512,每次迭代读取的批量为 10。这个简单的全连接网络以交叉熵为损失函数,并使用 Adam 优化算法进行权重更新。