一个小白的 TensorFlow 学习笔记(一)

雷博生 2017-09-13 582 标签: 深度学习人工智能

导语: 本系列文章以《深度学习原理与TensorFlow实践》一书的内容为基础,结合网络上其他材料,提取并梳理了一些感觉比较有意义的点,也记录了一个菜鸟的心路历程。好东西要大家分享,感觉这本书超赞的,拿来入门很合适。或许会有不对的地方,希望发现的人能指出来,谢谢。

1 写在前面

至于什么是AI人工智能,这里就不赘述了。人工智能中有一个分支叫做机器学习,机器学习中有一个分支叫做深度学习。机器学习是指从现实世界中获取大量数据并挑选有代表意义的样本交给算法处理,算法在这个基础上寻找特定的规律。我们提供的数据是多个维度的,即一个事物具有多个属性,例如房子的面积,地理位置,楼层等,这些属性影响了我们想要知道的结果,例如房价。那么我们说这些属性都是我们想要的特征,挑选出对我们求职结果有用的特征就叫做特征工程。那么可以看出机器学习对特征工程有着很高的依赖性,并且这种特征工程往往需要花费很多的时间和人力。于是,可以通过多层非线性变换的组合方式,得到更抽象也更有效的特征表示的深度学习诞生了。

2 步骤及概念

2.1 数据的清洗及预处理

数据的清洗是指对异常样本的处理,例如就我们的样本中某一字段发生了局部的缺失。处理这个异常我们可以:1.丢弃该样本(行) 2.丢弃缺失的字段(列) 3.填充默认值 4.填充平均值 。数据的预处理的目的是使凌乱的数据容易被算法处理,对此可以使用离散化,归一化,标准化以及数值变换等方法。

2.2 前向传播图

所谓前向传播,是指网络的正向计算,由输入计算出结果的过程。利用描绘好的模型(例如y=Wx+b, W和b是模型的参数,有训练获得),以及算法模型(例如逻辑回归,SVM等)。

2.3 代价函数

机器学习算法的优化需要依靠代价函数来评估优化方向。《深度学习原理与TensorFlow实践》一书中,以泰坦尼克问题为例(根据泰坦尼克号乘客的各种属性判断是否会幸存),这是一个二分类问题(幸存或者死亡),采用了求交叉熵的方式来作为代价函数。在已有样本中我们知道针对样本x的真实结果为y,而且根据上一步我们根据前向传播图也可以知道预测结果为y',这里是可以直接调用代价函数得到一个损失值,也就是一个代表预测结果与真实结果的差异值。

2.4 优化算法

使用代价函数得到了损失值,这个损失值,自然是越小越好,这代表了我们的预测正确概率很高。为了降低这个损失值,我们加入了优化算法。书中以随机梯度下降算法举例,还提到一些其他算法,但是笔者这里全都不知道,所以先着重学习了一下梯度下降算法。其实也有查过很多资料,但是觉得很多都不是很适合自己,可能是因为笔者的数学基础比较差。

先抛出自己现在的理解:所谓梯度,和斜率是差不多的概念,如果函数属于线性的,我觉得可以说梯度就是指斜率,导数。如果维度大于二维,那么函数会出现“山谷”,这个陡峭的程度就是梯度。感觉在某一点的梯度,一步一步往下寻找,找到山谷的底端。这有一篇文章,对于梯度下降的理解笔者觉得比较好。Gradient Descent 梯度下降法

2.5 迭代训练

有了上一步的优化算法,接下来要做的就是利用这个算法进行迭代训练。我们在迭代中不断从训练样本中抽取样本,代入我们的模型。利用优化算法去把损失最小化,也就是调整我们模型的参数。当迭代结束的时候我们的模型也就训练好了。

3 实操


# -*- coding: utf-8 -*-

import pandas as pd
import tensorflow as tf
import numpy as np

# 读取训练数据
data = pd.read_csv("train.csv")
# 显示数据属性:有多少行多少列以及每列的数据类型等
# data.info()

# sex字段如果时male赋值为1,否则赋值为0
data['Sex'] = data['Sex'].apply(lambda s: 1 if s == 'male' else 0)
# 缺失字段填充为0
data = data.fillna(0)

# 增加一列'身亡'
data['Deceased'] = data['Survived'].apply(lambda s: int(not s))

# 提取部分特征字段,数据集X为训练数据集,数据集Y为验证数据集
dataset_X = data[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare']]
dataset_X = dataset_X.as_matrix()
dataset_Y = data[['Deceased', 'Survived']]
dataset_Y = dataset_Y.as_matrix()

# 随机取20%的数据样本
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(dataset_X, dataset_Y, test_size=0.2, random_state=42)

with tf.name_scope('input'):
    # 定义占位符,因为算子定义时不直接参数运算(Feed机制),所以输入就用占位符表示
    X = tf.placeholder(tf.float32, shape=[None, 6]) # None代表可以输入任意条6元数据
Y = tf.placeholder(tf.float32, shape=[None, 2])

with tf.name_scope('classifier'):
    # 声明变量
    W = tf.Variable(tf.random_normal([6, 2]), name='weights')
    b = tf.Variable(tf.zeros([2], name='bias'))
    # 构造前向传播计
    y_pred = tf.nn.softmax(tf.matmul(X, W) + b)
    # 添加直方图参数概要记录算子
    tf.summary.histogram('weights', W);
    tf.summary.histogram('bias', b);

with tf.name_scope('cost'):
    # 声明代价函数
    cross_entropy = - tf.reduce_sum(Y * tf.log(y_pred + 1e-10), reduction_indices=1) # 根据交叉熵公式进行计算
    cost = tf.reduce_mean(cross_entropy) # 取所有样本的交叉熵平均值作为批量样本代价
    # 添加损失代价标量概要
    tf.summary.scalar('loss', cost)

# 使用随即梯度下降算法优化器来最小化代价
train_op = tf.train.GradientDescentOptimizer(0.001).minimize(cost)

with tf.name_scope('accuracy'):
    correct_pred = tf.equal(tf.argmax(Y, 1), tf.argmax(y_pred, 1))
    acc_op = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    tf.summary.scalar('accuracy', acc_op)

# 构建训练迭代过程
with tf.Session() as sess:
    # 初始化所有变量
    tf.global_variables_initializer().run()

    # 创建概要写入操作
    # TensorBoard可以通过命令'Tensorboard --logdir=./logs'来启动
    writer = tf.summary.FileWriter('./logs', sess.graph)
    # 方便起见,合并所有概要算子
    merged = tf.summary.merge_all()

    # 使用Saver保存训练好的模型,不必每次都需要训练
    saver = tf.train.Saver()

    # 进行训练(迭代10轮)
    for epoch in range(10) :
        total_loss = 0
        for i in range(len(X_train)) :
            feed = {X: [X_train[i]], Y: [Y_train[i]]}
            # 执行运算
            _, loss = sess.run([train_op, cost], feed_dict=feed)
            total_loss += loss
            summary, accuracy = sess.run([merged, acc_op],
                                     feed_dict={X: [X_train[i]], Y: [Y_train[i]]})
        writer.add_summary(summary, epoch)
        print('Epoch: %04d, total loss=%.9f' % (epoch + 1, total_loss))
    print 'Training complete!'

    # 评估校验数据集上的准确性
    pred = sess.run(y_pred, feed_dict={X:X_test})
    correct = np.equal(np.argmax(pred, 1), np.argmax(Y_test, 1))
    accuracy = np.mean(correct.astype(np.float32))
    print("Accuracy on validation set: %.9f" % accuracy)
    savePath = saver.save(sess, "model.ckpt")

4 写在最后

这边文章记录一下这个时刻的学习心得,后面或许还有修改,或者追加文章去补充。如果能帮助一起学习的就更好了~如果你觉得有哪里不正确,可以直接指出。