tensorflow 速成

Tensorflow

主要依赖包

Protocol buffer, bazel 此处偷乐3秒钟,哈哈哈哈

Bazel 支持的编译方式有 py_binary, py_library, py_test

挖坑:docker使用

tensor 张量

阶数和括号的数量一样,

一阶: []

二阶:[[],[]]

类型需要注意

1
2
3
4
5
import tensorflow as tf
a = tf.constant([1, 2], name="a") # dtype=tf.float32
b = tf.constant([2.0, 3.0], name="b")
result = tf.add(a, b, name="add")
print (result)

全联接层

2层之间任意2个节点都有边

$W$ 表示的是边,

snippet

1
2
3
4
5
config = tf.ConfigProto()  
config.gpu_options.allow_growth=True
with tf.Session(config=config) as sess:
print(sess.run(result))
print(result.eval(session=sess))

激活函数,非线性

ReLU

$f(x) = max(x, 0)$

sigmod

$f(x) = \frac{1}{1 + e^{-x}}$

tanh

$f(x) = \frac{1 - e^{-2x}}{1 + e^{-2x}}$

softmax

在分类问题中用来归一化最后输出的概率,使得它们的和为1

$softmax(y) = \frac{e^{yi}}{\sum_{j=1}^{n}e^{yi}}$

开始的输出的是每个类的概率,经过这个转换后变成了一个概率分布,强。

交叉熵

用来衡量2个概率分布的差异

$H(p,q) = -\sum_{x}p(x)log q(x)$

按照字面意思,如果交叉熵越大,那么2个概率分布应该会越大,那就错了!🍎🍎 吓得我吃了2个苹果

其实交叉熵的含义是指求熵的时候的交叉

反而,交叉熵越小,2个概率分布差距越小

tf.clip_by_value

tf.clip_by_value(v, low, upp)

1
2
3
4
5
6
7
8
v = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
with tf.Session(config=config) as sess:
print (tf.clip_by_value(v, 2.5, 4.5).eval(session=sess))

[[ 2.5 2.5 3. ]
[ 4. 4.5 4.5]]

* 和 matmul的区别

1
2
3
4
5
6
7
v1 = tf.constant([[1.0, 2.0], [3.0, 4.0]])
v2 = tf.constant([[5.0, 6.0], [7.0, 8.0]])
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
with tf.Session(config=config) as sess:
print((v1 * v2).eval(sessi fon=sess))
print(tf.matmul(v1, v2).eval(session=sess))

reduce_mean

0是列,1是行

1
2
3
4
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.]

random

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from numpy.random import RandomState
dataset_size = 10
X = rdm.rand(dataset_size, 2)
print (X)

[[ 0.5747115 0.6280762 ]
[ 0.28557628 0.58683334]
[ 0.75002176 0.85831384]
[ 0.75508219 0.69805725]
[ 0.86447943 0.322681 ]
[ 0.67078879 0.45087394]
[ 0.38210275 0.41081135]
[ 0.40147958 0.31738395]
[ 0.62191937 0.43024727]
[ 0.97380208 0.67780089]]

stochastic gradient descent

每次选一条数据进行计算损失函数

因为举个🌰, y=wx, 那么其实w的梯度是和x相关的。

batch 的方法

取个折中,使用部分的数据进行计算梯度

学习率的衰减

目的是使得前期的时候快速接近较优解,后期的时候不要有太大的波动。

1
2
decayed_learning_rate = \
learning_reate * decay_rate ^ (global_step / decay_steps)

其中decay_steps是所有数据数量总和/batch_size。所以用完一遍数据就*decay_rate一次

Global_step是当前的迭代次数。

tf参数staircase的含义

1
2
3
4
5
6
7
8
global_step = tf.Variable(0)

# 0.1 初始化学习率
# 每100次学习率 *0.96
learning_rate = tf.train.exponential_decay(0.1,
global_step, 100, 0.96, staircase=False)
learning_step = tf.train.GradientDescentOptimizer(learning_rate)\
.minimize(...my loss..., global_step=global_step)

正则化

L1

$R(w) = \sum_{i}|w_i|$

L2

$R(w) = \sum_{i}|w_i^2|$

理解

L1更佳容易使得参数等于0,因为在L2中如果一个数字为0.001平方后就很小了被忽略了。

计算技巧

交叉熵

y_ 是真实值

1
2
cross_entropy = -tf.reduce_mean(
y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))

真正的算法应该是对于矩阵 [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],先每行求和然后再取平均。现在是直接对所有的数字取了平均,这样不会改变结果因为差的是一个D系数。

总之在多分类问题中,

Ground truth是一堆概率值表示了这个东西属于某个类的概率

但是算法输出的也是一堆值,表示这个东西属于某个类的概率,但是不保证输出的概率和是1,所以通过exp{x}然后归一化后,使得概率的和为1,然后再通过交叉熵比较2个概率分布的差异。交叉熵越小的越好

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
import tensorflow as tf

def get_weight(shape, lambda):
var = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(lambda)(var))
return var

x = tf.placeholder(tf.float32, shape=(None,2))
y_= tf.placeholder(tf.float32, shape=(None,1))

batch_size = 8
layer_dimension = [2, 10, 10, 10, 1]
n_layers = len(layer_dimension)

cur_layer = x
in_dimension = layer_dimension[0]

for i in range(1, n_layers):
out_dimension = layer_dimension[i]
weight = get_weight([in_dimension, out_dimension], 0.0001)
bias = tf.Variable(tf.constant(0.1, shape=[out_dimension]))
cur_layer = tf.nn.relu(tf.matmul(cur_layer, weight) + bias)
in_dimension = layer_dimension[i]

mse_loss = tf.reduce_mean(tf.square(y_ - cur_layer))
tf.add_to_collection('losses', mse_loss)

loss = tf.add_n(tf.get_collection('losses'))

MNIST数字识别

6w张训练数据,1w张测试数据

图片大小是28*28,数字出现在正中间

白色背景 background

黑色前景 foreground

tf.cast(x, tf.float32) 类型强制转换

结论

调整网络结构对最后的影响很大

滑动平均模型和指数衰减都是限制神经网络中参数更新的速度,

正则化的作用更加大

变量管理

1
2
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0, shape=[1], name="v"))

升级api变化

tf.select->tf.where

疑问

1
2
3
4
5
w = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1))
y = tf.matmul(x, w)

loss = tf.reduce_mean(tf.square(y_ - y)) \
+ tf.contrib.layers.l2_regularizer(lambda)(w)
请作者喝一杯咖啡☕️