TensorFlow学习-上

Tensorflow使用

张量属性

  • name:名字
  • shape:维度,可能会被改变,但最好别改
  • dtype:类型,初始化后就不可变了

计算图

Tensorflow只会保存一个计算的流程,而不是直接出结果。相当于写公式。

In [3]: a = tf.constant([1.0,2.0])
In [4]: b = tf.constant([2.0,3.0])
In [5]: result = a + b
In [6]: result
Out[6]: <tf.Tensor 'add:0' shape=(2,) dtype=float32>

会话

会话用于执行公式,得出计算的结果。会话拥有并管理tf运行时的所有资源。所以用完需要关闭,否则会资源泄露。

with tf.Session() as sess:
    sess.run(公式)
    #退出作用域会自动关闭

#在交互模式下可以使用InteractiveSession
sess = tf.InteractiveSession()
result = a + b
result.eval()#自动使用sess

其他类

  • 配置类tf.ConfigProto

机器学习算法流程

  • 从物体中提取出特征向量
  • 定义一个合适的神经网络的结构
  • 调整神经网络中的参数值
//定义参数
EPOCHS = 500
......
//初始化变量
......

epoch = 0
while (!reachTarget() && epoch < EPOCHS){
    batchData = getBatchData() //获取batch大小的数据集
    result= trainForNerNet(batch)  //前馈NN得到预期值
    invUpdateForNN(value)          //反向传播更新矩阵值
    epoch++
}

从这里看,每次迭代都会产生一个result,显然这样会撑爆计算图,因此TF有placeholder来作为单个填充位置。placeholder不用指定值和维度,只要给定数据类型。
- 验证效果

神经网络的层之间的连接

如第一层(为输入层)是2个节点,而第二层是3个节点,那么从第一层到第二层的映射,是一个2*3的矩阵。

W1 = [[w11, w12, w13],
     [w21, w22, w23]]
X1 = [x1, x2]

生成的第二层的结果是一个1*3的矩阵,正好对于第二层的3个节点

X2 = X1 * W1

如果第三层就是输出层,只有一个节点,那么第二层到第三层的映射为3*1的矩阵

W2 = [[w11],
      [w21],
      [w31]]
X3 = X2 * W2

最后只有一个值,即为输出值。

实现这个神经网络

  • 矩阵乘法为
    tf.matmul(X, W)
  • 生成一个正态分布的映射矩阵
weights = tf.Variable(tf.random_normal([2, 3], stddev=2))
  • 其他生成映射矩阵的函数
tf.random_normal    #标准正态分布
tf.truncated_normal #无离群值(99%以外)的正态分布
tf.random_uniform   #平均分布
tf.random_gamma     #Gamma分布(没听过)

tf.zeros            #全0的矩阵
tf.ones             #全1的矩阵
tf.fill             #全某数的矩阵

tf.constant         #自定义常量矩阵
  • 在计算出结果前,变量需要初始化
w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1)
...
y = tf.matmul(a, w1)

sess = tf.Session()
sess.run(tf.initialize_all_variables()) #先初始化所有变量
sess.run(y)              #才能开始计算
sess.close()
  • placeholder的使用
w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1)

x = tf.placeholder(tf.float32,    #类型必需
                   shape = (1,2)) #维度最好有,可避免出错

y = tf.matmul(x, w1)

sess = tf.Session()
sess.run(tf.initialize_all_variables()) #先初始化所有变量
sess.run(y, feed_dict={x: [0.7,0.9]})              #才能开始计算, 并要往placeholder中填充数据
sess.close()
  • 实现反向传播算法
cross_entropy = -tf.reduce_mean(
    y * tf.log(tf.clip_by_value(y,1e-10,1.0)))
learning_rate = 0.001
train_step = tf.train.AdamOptimizer(learning_rate)
    .minimize(cross_entropy)

模型持久化

saver = tf.train.Saver()
# 保存模型
saver.save(sess, "/path/model.ckpt")
# 加载模型
saver.restore(sess, "/path/model.ckpt")

#直接加载
saver = tf.train.import_meta_graph(..)

深度学习

基本概念

一类通过多层非线性变换对高复杂性数据建模算法的合集

线性模型的局限

一个线性模型如下

Y = x * W1 * W2 * W3
  = x * W

他再怎么变换(即无论怎么多层),还是一个线性模型
因此只能解决线性可分问题,无法解决XOR问题
要解决复杂问题,需要非线性模型,如relu

去线性化

一个二层模型如下

Y = f(f(x*W1+b1)*W2+b2)

常用的变换函数如下
- ReLU
- sigmid
- tanh

经典损失函数

交叉熵:两个概率分布之间的距离,多用于分类问题
  • 如一个三分类问题
  • 如输出的结果为[0.12, 0.79, 0.09], 而预期的结果y为[0, 1, 0], 那么使用交叉熵能够计算这两个结果之间的距离
softmax回归:将原始输出层映射到最终输出层,映射成为一个概率值
  • 一般是通过softmax回归将输出值进行一次映射,成为最终概率
  • 再将最终概率与目标值之间,进行交叉熵计算距离
  • 反向传播以更新值
  • tf.clip_by_value: 设定上下限,比下限小的设为下限,比上限大的设为上限
  • tf.nn.softmax_cross_entropy_with_logits(y, y_)
均方误差:用于回归问题
  • mse = tf.reduce_mean(tf.square(y_ - y))
自定义损失函数
#如下述函数
def f(x,y):
    if x > y:
        return A * (x - y)
    else:
        return B * (y - x)

def loss(y, y_):
    sum = 0
    for i in range(len(y)):
        sum += f(y, y_)
    return sum

# 在tensorflow中
tf.reduce_sum(
        tf.select(
            tf.greater(v1, v2),
            (v1 - v2) * a,
            (v2 - v1) * b
        )
    )

优化算法

批量梯度下降:选择一小批数据,进行优化
设置学习率, 衰减学习率
decayed_learning_rate
  = learning_rate * decayed_rate ^ (step / decay_steps)

# TF自带的
step = tf.Variable(0)

learning_rate = 
  tf.train.exponential_decay(0.1, global_step, 100, 0.96, staircase=true)

learning_step =   
  tf.train.GradientDescentOptimizer(learning_rate)
    .minimize(loss_func, global_step = step)
过拟合问题
  • L1正则化:sum(X)
tf.contrib.layers.l1_regularizer
  • L2正则化:sum(X ** 2)
tf.contrib.layers.l2_regularizer
  • 这两个正则化可以一起使用
滑动平均模型
  • tf.train.ExponentialMovingAverage

卷积神经网络

简介

一张图片的像素太多了,而全连接层的每一个节点都要接受所有像素作为参数。如一张图片为30*30,而第二层(第一层隐藏层)假设有500个节点,那么所有参数为30*30*500+500个。

而卷积就是用于减少参数数量的,还能避免过拟合。

CNN的组成

  • 输入层:接受所有像素
  • 卷积层:通常为3*3或5*5个节点映射为一个节点,矩阵会变深,抽象层次更高
  • 池化层:不会改变三维矩阵的深度,会减小长和宽,简而言之就是将高像素的图片变成低像素的
  • 全连接层:在多轮卷积和池化后,连接入全连接层分类。将卷积层和池化层视为信息特征的提取,而全连接层就是训练了
  • SoftMax层:给出概率结果

卷积层

卷积层每个节点又叫过滤器:将当前神经网络中的一个子矩阵映射为下一层矩阵的一个值。

X2 = f(X1 * W + b)

#在tf中
# 填充的值,由正态分布生成
initer = tf.truncated_normal_initializer(stddev=0.1)
# 生成一个5*5卷积核,当前层深度为3(RGB),输出层为16
filter_weight = tf.get_variable("weight", [5,5,3,16], initializer=initer)
# 生成偏差项
biases = tf.get_variable('biases', [16], initializer=tf.constant_initializer(0.1))

# 定义卷积层
conv = tf.nn.conv2d(input,         #上面的X1
                    filter_weight, #上面的W
                    strides=[1,1,1,1],#步长
                    padding='SAME')
# 加上偏差项
bias_cnn = tf.nn.bias_add(conv, biases)
# 上面的f()
actived_cnn = tf.nn.relu(bias_cnn)

这里写图片描述
△卷积核为3、步幅为1和带有边界扩充的二维卷积结构
- input: 一个四维矩阵,第一维为一个batch,后三维表示一张图片。如[0,:,:,:]表示第一张图片
- filter_weight:卷积层的权重
- stride: 不同维度上的步长大小。第一个1表示图片,必然是1,总不能跳过图片吧。最后一个1表示色彩通道,也必然为1,总不能跳过一种颜色吧。中间两个可以改变,表示在长宽上的移动步长。
- padding:表示填充,SAME为全0填充,VALID为不填充

池化层

这是一种特殊的卷积,其深度不变,只减少长宽。公式如下
X2 = X1 * W
  • 最大池化层:tf.nn.max_pool
  • 平均池化层:tf.nn.avg_pool
    这里写图片描述
pool = tf.nn.max_pool(actived_conv,
                      ksize=[1,3,3,1],
                      strides=[1,2,2,1],
                      padding='SAME')
  • actived_conv: 卷积层输出值
  • ksize: 过滤器尺寸, 常用的为[1,3,3,1]或[1,2,2,1]
  • strides: 步长
  • padding:填充

经典CNN模型

LeNet-5
  • AlexNet
  • ZF Net
  • VGGNet
# 一个正则表达式,哈哈哈
输入层 -> (卷积层 -> 池化层?)+ -> 全连接层+

这里写图片描述

Inception

Google的这个模型和上面显然是两个思路,AlexNet发明的时代,计算机资源不算强大,想的是减少参数还能达到模型效果。

Inception是反复从图像中抽取特征信息,宁可抓错也不放过,得益于Google的强大计算能力,显然这样可以得到更多的信息。效果自然很好。
这里写图片描述
这里写图片描述

TensorFlow-Slim

这是一个封装包

# 定义一个卷积层, 32表示下一层的深度, [3,3]为核大小
net = slim.conv2d(input, 32, [3,3])

迁移学习

将一个问题上训练好的模型,通过简单调整使其适用于别的问题。大幅减小训练量,和训练时间。有时候只需要替换最后一层,其他层被称为瓶颈层。
优点是减少训练时间,效果还不错
缺点是准确度不如大样本,重新训练高
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值