tensorflow的一些总结、LSTM图像分类实现

最近论文需要用到深度学习,发现一年没用过的tensorflow,基本上都忘了。这篇文章是北大软微曹健老师的视频笔记

基础

在tensorflow中,用张量表示数据,用计算图搭建神网络,用会话(session)执行计算图,优化线上的权重,得到模型。
张量: n维数组,0阶是标亮、1阶是向量、2阶是矩阵、n阶就是张量了
计算图: 搭建神经网络的计算过程,只搭
看一个最简单的计算图:

import tensorflow as tf
a = tf.constant([1.0, 2.0])
b = tf.constant([3.0, 4.0])
result = a + b
print(result)

结果

Tensor("add:0", shape=(2,), dtype=float32)

这里可以看出来,计算图只描述计算过程,不计算运算结果

会话: 如果要得到计算图的计算结果,就需要使用会话

with tf.session() as sess:
	print(sess.run(result))

参数
Variable表示 tensorflow 中的变量,线上的权重W,用变量表示,随机给初值

# random_normal表示生成标准正太分布的矩阵,其他可选的还有 truncated_normal() ->去掉过大偏离点的正态分布 random_uniform ->平均分布
# [2,3]表示矩阵为两行三列的矩阵
# stddev表示矩阵的标准差为2
# mean表示均值为0
# seed是随机种子,如果不设置,每次生成的随机数会不一样
w = tf.Variable(tf.random_normal([2,3], stddev=2, mean=0, seed=1))

tf.zeros([3,2], int32) #三行两列的全0数组
tf.ones([3,2], int32) #三行两列的全1数组
tf.fill([3,2],6) #三行两列,数组值全是6
tf.constant([3,2,1]) #直接生成[3,2,1] tensorflow中运算,就需要使用tensorflow的数据格式

占位符
在神经网络的训练中输入参数可能有多组,用placeholder来接收输入参数x

x = tf.placeholder(tf.float32, shape(1,2)) #生成一个一行两列的占位符

全局参数初始化
Variable生成的过程,只是指定了初始化的方式,由于计算图本身不进行任何运算,因此并没有真正初始化,如果要初始化就需要使用下面的方式:

with tf.Session() as sess:
	init_op = tf.global_variables_initializer()
	sess.run(init_op)
一个简单训练的实现过程

神经网络的实现过程大致可以分为以下几步:

  1. 准备数据集,提取特征,作为输入喂给神经网络
  2. 搭建NN结构,从输入到输出(包括搭建计算图,会话执行,前向传播)
  3. 大量特征数据喂给NN,迭代优化NN参数(反向传播,优化参数,训练模型)
  4. 使用训练好的模型预测和分类

下面看一个简单的例子:

import tensorflow as tf
import numpy as np
BATCH_SIZE = 8
seed = 23455

# 准备数据集
rng = np.random.RandomState(seed)
X = rng.rand(32, 2) #产生32行2列的随机矩阵
Y = [[int(x0+x1<1)] for (x0,x1) in X]
print(Y)

# 搭建网络结构
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))

w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3,1], stddev=1, seed=1))

a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
loss = tf.reduce_mean(tf.square(y-y_))
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss)
#train_step = tf.train.MomentumOptimizer(0.001).minimize(loss)
#train_step = tf.train.AdamOptimizer(0.001).minimize(loss)

#训练模型
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    STEPS = 3000
    for i in range(STEPS):
        start = (i*BATCH_SIZE) % 32
        end = start + BATCH_SIZE
        sess.run(train_step, feed_dict={x: X[start: end], y_ : Y[start: end]})
        if i % 500 == 0:
            total_loss = sess.run(loss, feed_dict={x:X, y_:Y})
            print("After %d training step(s), loss on all data is %g" % (i, total_loss))
print("end")
神经网络的优化

激活函数,常用的有

tf.nn.relu()
tf.nn.sigmoid()
tf.nn.tanh()

损失函数 常用的有:

#均芳误差
loss_mse = tf.reduce_mean(tf.square(y_ - y))

#交叉熵表示两个概率分布之间的距离,越大距离越远
#y小于1e-12为1e-12,大于1.0为1.0(这就要求输入数据都在0-1之间,毕竟是概率)
ce = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-12, 1.0)))

#如果输出不满足 0-1 的要求,就无法使用交叉熵,这个时候可以让输出经过softmax来满足这一点
#tf.argmax()和np.argmax()效果一样,只是需要运行才能有最终的结果
#如果axis=0,返回列最大元素所在的索引,如果axis=1,返回行最大元素的索引(由于标签大多数是one-hot的形式,每一行1所在的元素就是正确的类别)
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, axis=1))
cem = tf.reduce_mean(ce)

自定义损失函数
下面的损失函数表示,如果y大于y_,执行第一个式子,COST(y-y_),否则执行第二个式子,PROFIT(y_-y)

loss = tf.reduce_sum(tf.where(tf.greater(y, y_), COST*(y-y_), PROFIT*(y_ - y)))

学习率:
普通学习率的设置上面已经用过了,这里记录下指数衰减的学习率

 learning_rate = tf.train.exponential_decay(
	LEARNINF_RATE_BASE,	#学习率基础
	global_step,	#运行多少轮
	LEARNING_RATE_STEP,	#多久更新一次学习率,一般就是 总样本数/batch_size
	LEARNING_RATE_DECAY,	#学习衰减率(0,1)
	staircase=True
)

滑动平均
也叫影子值,记录了每个参数一段时间过往值的平均,增加了模型的泛化性(就好像给参数加上了影子,参数变化,影子缓慢跟随)

影子 = 衰减率 * 影子 + (1-衰减率)* 参数
衰减率 = min{MOVING_AVERAGE_DECAY, (1+轮数)/(10+轮数)}

其中 MOVING_AVERAGE_DECAY 是超参数(一般是一个比较大的数,比如0.99)
tf中使用滑动窗口平均

#global_step 当前轮数
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY), global_step)

# ema_op = ema.apply([])
ema_op = ema.apply(tf.trainable_variables())	#trainable_variables可以将所有待训练的参数整理成列表的形式返回
with tf.control_dependencies([train_step, ema_op]):
	train_op = tf.no_op(name='train')
	
# 返回某些参数的滑动平均值
ema.average(参数名)

正则化:

loss(w) = tf.contrib.layers.l1_regularizer(REGULARIZER)(w)	#l1正则化项
loss(w) = tf.contrib.laryers.l2_regularizer(REGULARIZER)(w) #l2正则化项

# 把内容加到集合对应位置做加法
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
loss = cem + tf.add_n(tf.get_collection('losses')) #再加上交叉熵为总loss
模块化的神经网络搭建

前向传播(forward.py):

def forward(x, regularizer):
	w=
	b=
	y=
	return y
	
def get_weight(shape, reguarizer):
	w = tf.Variable( ) #赋初值
	tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w)) #将w的损失加入到总损失losses中
	return w
	
def get_bias(shape):
	b = tf.Variable( )	#赋初值
	return b

反向传播(backward.py)

def backward():
	x = tf.placeholder( )
	y_ = tf.placeholder( )
	y = forward.forward(x, REGULARIZER)
	global_step = tf.Variable(0, trainable=False)
	loss = # 这里有多种,前面的交叉熵、均方误差都可以
	loss = loss + tf.add_n(tf.get_collection('losses'))	# 加入正则化项
	learning_rate = #这里学习率可以是固定值,也可以是前面说到的指数衰减学习率	

大概就是这么个流程,视频后面内容没看了。

LSTM实现手写数字识别
# 使用rnn实现mnist数据集分类
# 了解rnn的基本结构和实现

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

lr = 0.001
training_iters = 100000
batch_size = 128

#28*28的图片,每个向量是一行,一共28行
n_input = 28
n_step = 28
n_hidden_unis = 128
n_classes = 10

x = tf.placeholder(tf.float32, [None, n_step, n_input])
y = tf.placeholder(tf.float32, [None, n_classes])

weights = {
    'in' : tf.Variable(tf.random_normal([n_input, n_hidden_unis])),
    'out' : tf.Variable(tf.random_normal([n_hidden_unis, n_classes]))
}

biases = {
    'in' : tf.Variable(tf.constant(0.1, shape=[n_hidden_unis,])),
    'out' : tf.Variable(tf.constant(0.1, shape=[n_classes,]))
}

def RNN(X, weights, biases):
    #: X[batch_size,28,28] -> X[128*28, 28]
    X = tf.reshape(X, [-1, n_input])
    X_in = tf.matmul(X, weights['in']+biases['in'])

    #: x_in[128*28,128] -> x_in[128,28,128]
    X_in = tf.reshape(X_in, [-1, n_step, n_hidden_unis])

    # cell: forget_bias=1.0 表示不希望忘记前面的东西    state_is_tuple
    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden_unis, forget_bias=1.0, state_is_tuple=True)
    _init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)

    #time_major=False time_step 不是第一个维度
    outputs, state = tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state = _init_state, time_major=False)

    # hidden layer for output as the final result
    # tf.transpose(outputs, [1,0,2])) 将第一和第二两个维度交换(维度1换到0的位置,就是第一个维度,维度0换到1的位置就是第二个维度)
    outputs = tf.unstack(tf.transpose(outputs, [1,0,2]))
    result = tf.matmul(outputs[-1], weights['out']+biases['out'])
    # results = tf.matmul(state[1], weights['out']) + biases['out'] 在这个例子中和上面结果是一样的
    return result



pred = RNN(x, weights, biases)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
train_op = tf.train.AdamOptimizer(lr).minimize(cost)

correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))    #one-hot编码的预测结果
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))    #tf.cast数据类型变换

init = tf.initialize_all_variables()
with tf.Session() as sess:
    sess.run(init)
    step = 0
    while step * batch_size < training_iters:
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        batch_xs = batch_xs.reshape([batch_size, n_step, n_input])
        sess.run([train_op], feed_dict={
            x: batch_xs,
            y: batch_ys
        })
        if step % 20 == 0:
            print(sess.run(accuracy, feed_dict={
                x: batch_xs,
                y: batch_ys
            }))

        step += 1
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值