最近学习tensorflow,这里做一个小总结,先说一下我的运行环境,win10+Anaconda3.5,导入tensorflow。
首先提供一个trick,对于一些初次见到的API接口,有时候直接百度搜索出来的答案七七八八的不好看懂,中文官方手册也不是很方便,提供一个比较简单的方法:
(1)打开命令提示符;
(2)输入python;
(3)如下输入
import tensorflow as tf
help(tf.contrib.layers.batch_norm)
注:help()括号里面放你需要查询的函数
—————————————————————————————————————小白记
Tensorflow是一套深度学习开源软件库。从实现上来说,它的计算核心是基于高性能C/C++实现的,外部封装使用了简单的Python语言。
这里简单介绍汇总了一些tensorflow的常用接口,方便以后查询。
1 使用placeholder声明输入占位符
tf.placeholder ()函数
placeholder(
dtype,
shape=None,
name=None
)
比如:
X = tf.placeholder("float", [None, n_input])
或
x = tf.placeholder(tf.float32, shape=(1024, 1024))
后面的shape参数中第一个为行数,第二个为列数,若显示为None,表示同时放入任意条记录
2 声明参数变量
tf.variable ()函数
W = tf.Variable(tf.random_normal([6, 2]), name = 'weights')
b = tf.Variable(tf.zeros([2]), name = 'bias')
或
weights = {
'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
'decoder_h1': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
'decoder_b1': tf.Variable(tf.random_normal([n_input])),
}
可以定义变量的类型,形状,名称,有点类似前面的tf.placeholder ()
3 构造前向传播计算图
tf.nn.softmax()函数
softmax(logits, axis=None, name=None, dim=None)
比如:
y_pred = tf.nn.softmax(tf.matmul(input, W) + bias)
其中,logits指的是一个非空的张量,它的数据类型只能为以下几种:half,float32,float64。
另外,softmax函数指的是一个归一化的指数函数。若输入数据是c维度的向量z,那么softmax函数的数据也是一个C维度的向量y,里面的值是0或者1。softmax函数的定义式如下:
下面对这一块内容做一个解释。所谓前向传播就是网络正向计算,由输入计算出标签的过程。在这行语句中,tf.matmul()是矩阵乘法算子,tf.nn.softmax()是softmax函数。另外,对于偏置向量bias,可以直接用加号“+”完成矩阵相加操作,这与Numpy等库用法类似。Tensorflow中的Tensor对象和Variable对象都对常用四则运算符号进行过重载,运用很灵活。
4 声明代价函数
tf.reduce_sum()函数
reduce_sum (
input_tensor ,
axis = None ,
keep_dims = False ,
name = None ,
reduction_indices = None
)
参数:
input_tensor:要减少的张量。应该有数字类型。
axis:要减小的尺寸。如果为None(默认),则缩小所有尺寸。必须在范围[-rank(input_tensor), rank(input_tensor))内。
keep_dims:如果为true,则保留长度为1的缩小尺寸。
name:操作的名称(可选)。
reduction_indices:axis的废弃的名称。
函数中的input_tensor是按照axis中已经给定的维度来计算的;除非keep_dims是true,否则张量的秩将在axis的每个条目中减少1;如果keep_dims为true,则减小的维度将保留为长度1。
如果axis没有条目,则缩小所有维度,并返回具有单个元素的张量。
比如:
x = tf.constant([[1, 1, 1], [1, 1, 1]])
tf.reduce_sum(x) # 6
tf.reduce_sum(x, 0) # [2, 2, 2]
tf.reduce_sum(x, 1) # [3, 3]
tf.reduce_sum(x, 1, keep_dims=True) # [[3], [3]]
tf.reduce_sum(x, [0, 1]) # 6
tf.reduce_mean()函数
reduce_mean(
input_tensor,
axis=None,
keep_dims=False,
name=None,
reduction_indices=None
)
参数:
input_tensor:要减少的张量。应该有数字类型。
axis:要减小的尺寸。如果为None(默认),则减少所有维度。必须在[-rank(input_tensor), rank(input_tensor))范围内。
keep_dims:如果为true,则保留长度为1的缩小尺寸。
name:操作的名称(可选)。
reduction_indices:axis的不支持使用的名称。
返回:
该函数返回减少的张量。
numpy兼容性
相当于np.mean
比如:
x = tf.constant([[1., 1.], [2., 2.]])
tf.reduce_mean(x) # 1.5
tf.reduce_mean(x, 0) # [1.5, 1.5]
tf.reduce_mean(x, 1) # [1., 2.]
这两个函数基本类似
这里给出一个计算代价函数的例子,首先给出它的计算公式:
# 使用交叉熵作为代价函数
cross_entropy = -th.reduce_sum(y * tf.log(y_pred + 1e-10), reduction_indices = 1)
# 批量样本的代价值为所有样本交叉熵的平均值
cost = tf.reduce_mean(cross_entropy)
5 加入优化算法
tf.train.RMSPropOptimizer()函数
Tensorflow内置了多种经典的优化算法,如随机梯度下降法(SGD),动量算法(Momentum),Adagrad算法,ADAM算法,RMSProp算法。另外还有在线学习算法FTRL。优化器内部会自动构建梯度计算和反向传播部分的计算图。
一般对于优化算法,最关键的参数是学习率,对于学习率的设定是一门技术。而且,不同的优化算法在不同的问题上可能会有不同的收敛速度,在解决问题时可以做多种尝试。
这里给出一个例子:
# 使用随机梯度下降算法优化器来最小化代价,系统自动构建反向传播部分的计算图
optimizer = tf.train.RMSPropOptimizer(learning_rate).minimize(cost)
6 构建模型的训练过程
sess.run()函数
Session启动后就正式进入了训练过程。首先要做的就是使用初始化所有变量,方法是:
# 初始化所有变量,必须最先执行
tf.global_variables_initializer()
Session.run(fetches, feed_dict=None, options=None, run_metadata=None),其中有两个关键的参数,fetches指定需要被计算的节点,可以用数组同时指定多个节点。计算所需要的数据则由feed_dict代入。feed_dict需要传入一个字典,字典的key是输入占位符placeholder,value为真实的输入数据(另外,有一点要声明,参数fetches指定的东西,必须是前面指定过的,不能是之后出现的)。
Session.run()执行完计算之后,会返回计算节点的结果。若节点为算子(算子是一个函数空间到函数空间上的映射O:X→X),则没有返回值,若节点是tensor,则返回当前值。最常见的是优化算子和代价函数tensor的组合,前者不需要返回值,后者计算得到的代价值将会返回,比如(需要注意的是tensorflow并没有计算整个图,只是计算了与想要fetch 的值相关的部分):
—,loss = sess.run(fetches = [train_op, cost], feed_dict=feed)
7 存储和加载模型参数
save()函数
用于存储模型:
# save(sess, path)
save_model = "model_aed_previous/model_aed_previous"
saver = tf.train.Saver()
saver.save(sess, save_model_path)
restore()函数
用于提取模型
# restore(sess, path)
save_model = "model_aed_previous/model_aed_previous"
saver = tf.train.Saver()
saver.restore(sess, save_model_path)
这两个函数不作解释,会用就好。
在上面的程序示例中,由Saver.save()触发的存储操作会生成4个文件。第一个是名为“model.ckpt”的文件,这个文件是真实存储变量及其取值的文件。第二个是名为“model.cpkt.meta”的描述文件,在这个文件存储的是MetaGraphDef结构的对象经过二进制序列化后的内容。MetaGraphDef结构由Proyocol buffer定义,其中包含了整个计算图的描述,各个变量定义的声明,输入管道的形式,以及其它的信息。meta文件可以在没有计算图声明代码的情况下载入模型,而若在应用时还有原始的python程序代码,程序就可以重新构建计算图的基本信息,则加载时只需要“model.ckpt”一个文件即可。第三个文件是以“model.ckpt.index”为名称的文件,存储了变量在checkpoint文件中的位置索引。最后一个是名为“checkpoint”的文件,这个文件中存储了最新存档的文件路劲
8 tensorflow实现三层自编码机
前面给出的都是分块的,如果需要对整个流程有了解还是得看整块代码,这里给出一个tensorflow实现三层自编码机模型的例子。
# 这里就涉及到学习参数的问题了,学习率,迭代次数,小批次
learning_rate = 0.01
training_epochs = 10
batch_size = 256
display_step = 1
# 隐藏层的结点数,输入层的结点数
n_hidden_1 = 50
n_input = train_x.shape[1]
# tuple使用()表示不可变序列,list使用[]表示可变序列,shape参数的[None, n_input]表示行数不固定,列数为属性数
X = tf.placeholder("float", [None, n_input])
# 定义了权重矩阵和偏置参数(先设为随机数)
weights = {
'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
'decoder_h1': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
'decoder_b1': tf.Variable(tf.random_normal([n_input])),
}
# 定义了编码和解码函数,tf.matmul(x,y)表示将矩阵a乘以b,tf.add(a, b)表示a和b相加,tf.nn.sigmoid()则是单纯的激活函数了,每个神经元输出的是一个单值
def encoder(x):
layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']), biases['encoder_b1']))
return layer_1
def decoder(x):
layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']), biases['decoder_b1']))
return layer_1
# 这里则是完全描绘出了一个具体的自编码机模型,这里的tf.reduce_mean()定义了损失函数,用的是方差,cost是损失函数,optimizer定义了优化器
# 对于函数tf.reduce_mean(),这里给出它的解释tf.reduce_mean(x)表示求一个矩阵的总体平均值,tf.reduce_mean(x, 0)表示求一个矩阵的列平均值,得到一个行向量
# tf.reduce_mean(x, 1)表示求一个矩阵的行平均值,得到一个列向量
encoder_op = encoder(X)
decoder_op = decoder(encoder_op)
y_pred = decoder_op
y_true = X
batch_mse = tf.reduce_mean(tf.pow(y_true - y_pred, 2), 1)
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2))
optimizer = tf.train.RMSPropOptimizer(learning_rate).minimize(cost)
# save_model = "model_aed_previous/model_aed_previous"
# # save_model = "model_aed_next/model_aed_next"
# saver = tf.train.Saver()
# init = tf.global_variables_initializer()
# with tf.Session() as sess:
# now = datetime.now()
# sess.run(init)
# total_batch = int(train_x.shape[0] / batch_size)
# for epoch in range(training_epochs):
# for i in range(total_batch):
# batch_idx = np.random.choice(train_x.shape[0], batch_size)
# batch_xs = train_x[batch_idx]
# _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
# if epoch % display_step == 0:
# train_batch_mse = sess.run(batch_mse, feed_dict={X: train_x})
# print("Epoch:", '%04d' % (epoch + 1),
# "cost=", "{:.9f}".format(c),
# "Train auc=", "{:.6f}".format(auc(train_y, train_batch_mse)),
# "Time elapsed=", "{}".format(datetime.now() - now))
# print("Optimization Finished!")
# save_path = saver.save(sess, save_model)
# print("Model saved in file: %s" % save_path)
# save_model = "model_aed_previous/model_aed_previous"
# 这里要使用模型开始预测了
# tf.train.Saver()用于先创建一个saver对象
# tf.global_variables_initializer添加用于初始化变量的节点
# sess.run()的作用是计算整个张量图,feed_dict的作用是给使用placeholder创建出来的tensor赋值,给出了损失函数
# 这里也计算了预测准确度(这里算的究竟是什么的准确率)
# restore()函数是模型恢复函数,参数为restore(sess, save_path),save()函数用于保存模型,参数为save(sess, save_model)
save_model = "model_aed_next/model_aed_next"
saver = tf.train.Saver()
init = tf.global_variables_initializer()
with tf.Session() as sess:
saver.restore(sess, save_model)
test_batch_mse = sess.run(batch_mse, feed_dict={X: test_x})
# 这里算的不是正确率,算的是ROC?
print("Test auc score: {:.6f}".format(auc(test_y, test_batch_mse)))
# save_model = "model_aed_previous/model_aed_previous"
# 这里给出了预测集和训练集两者的样本大小,却没有计算其准确率
save_model = "model_aed_next/model_aed_next"
saver = tf.train.Saver()
init = tf.global_variables_initializer()
with tf.Session() as sess:
saver.restore(sess, save_model)
test_encoding = sess.run(encoder_op, feed_dict={X: test_x})
train_encoding = sess.run(encoder_op, feed_dict={X: train_x})
print("Dim for test_encoding and train_encoding are:", test_encoding.shape, train_encoding.shape)
这里面同时有训练和测试的代码,时间问题,这里不过多叙述,应该还好理解,欢迎大家共同学习交流~~~