python流处理框架_《基于Python玩转人工智能最火框架 TensorFlow应用实践》学习笔记...

pip install --upgrade tensorflow

# 其它所需包

pip install --upgrade numpy pandas matplotlib

本文主要内容

TensorFlow的基础知识TensorFlow经典的数据流图

TensorFlow的Hello World

TensorBoard

TensorFlow的操作(Operations)

TensorFlow的使用案例梯度下降解决线性回归

激活函数(Activation Function)

实现CNN(Convolution Neural Network)卷积神经网络

RNN-LSTM循环神经网络

TensorFlow的基础知识

TensorFlow经典的数据流图

图中的各个节点是操作(Operation)中间的线是张量(Tensor)

TensorFlow的Hello Worldimport tensorflow as tf

# 创建一个常量Operation

hw = tf.constant("Hello World!")

# 启动会话

sess = tf.Session()

# 运行Graph计算图

print(sess.run(hw))

# 关闭会话

sess.close()

Tensor有以下几种constant(常量), Variable(变量), placeholder(占位符),SparseTensor(稀疏张量)

TensorBoard# 1.用TensorFlow保存图的消息到日志中

tf.summary.FileWriter(path, sess.graph)

# 2.用TensorBoard读取并展示日志命令行

tensorboard --logdir=日志所在路径

如以下是后面卷积神经网络示例的TensorBoard

TensorFlow的操作(Operations)

TensorFlow的使用案例

梯度下降解决线性回归

import numpy as np

import matplotlib.pyplot as plt

import tensorflow as tf

# 构建数据

points_num = 100

vectors = []

# 用Numpy的正态随机分页函数生成100个点

# 这些点的(x,y)坐标值对应线性方程 y = 0.1 * x + 0.2

for i in range(points_num):

x1 = np.random.normal(0.0, 0.66)

y1 = x1 * 0.1 + 0.2 + np.random.normal(0.0, 0.04)

vectors.append([x1, y1])

x_data = [v[0] for v in vectors] # 真实点的x坐标

y_data = [v[1] for v in vectors] # 真实点的y坐标

# 图像1展示100个随机数据点

plt.plot(x_data, y_data, 'r*', label="Original data") # 红色星形的点

plt.title("Linear Regression using Gradient Descent")

plt.legend()

plt.show()

# 构建线性回归模型

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) # 初始化 Weight

b = tf.Variable(tf.zeros([1])) # 初始化 Bias

y = W * x_data + b # 模型计算出来的y

# 定义 loss function(损失函数) 或 cost function(代价函数)

# 对 Tensor的所有维度计算 ((y - y_data) ^ 2)之和 / N

loss = tf.reduce_mean(tf.square(y - y_data))

# 用梯度下降的优化器来优化我们的 loss function

optimizer = tf.train.GradientDescentOptimizer(0.5) # 设置学习率0.5

train = optimizer.minimize(loss)

# 创建会话

sess = tf.Session()

# 初始化数据流图中的所有变量

init = tf.global_variables_initializer()

sess.run(init)

# 训练 20 步

for step in range(20):

# 优化每一步

sess.run(train)

# 打印出每一步的损失、权重和偏差

print("Step=%d, Loss=%f, [Weight=%f Bias=%f]" % (step, sess.run(loss), sess.run(W), sess.run(b)) )

# 图像2 绘制所有的点并且绘制出最佳拟合的直线

plt.plot(x_data, y_data, 'r*', label="Original data") # 红色星形的点

plt.title("Linear Regression using Gradient Descent")

plt.plot(x_data, sess.run(W) * x_data + sess.run(b), label="Fitted line") # 拟合的线

plt.legend()

plt.xlabel('x')

plt.ylabel('y')

plt.show()

# 关闭会话

sess.close()

import numpy as np

import matplotlib.pyplot as plt

import tensorflow as tf

# 创建输入数据

x = np.linspace(-7, 7, 180) # (-7, 7)之间等间隔的180个点

#激活函数的原始实现

def sigmoid(inputs):

y = [1 / float(1 + np.exp(-x))  for x in inputs]

return y

def relu(inputs):

y = [x * (x>0) for x in inputs]

return y

def tanh(inputs):

y = [(np.exp(x) - np.exp(-x)) / float(np.exp(x) + np.exp(-x)) for x in inputs]

return y

def softplus(inputs):

y = [np.log(1 + np.exp(x)) for x in inputs]

return y

# 经过 TensorFlow的激活函数处理的各个 Y值

y_sigmoid = tf.nn.sigmoid(x)

y_relu = tf.nn.relu(x)

y_tanh = tf.nn.tanh(x)

y_softplus = tf.nn.softplus(x)

# 创建会话

sess = tf.Session()

# 运行

y_sigmoid, y_relu, y_tanh, y_softplus = sess.run([y_sigmoid, y_relu, y_tanh, y_softplus])

# 创建各个激活函数的图像

plt.subplot(221)

plt.plot(x, y_sigmoid, c="red", label="Sigmoid")

plt.ylim(-0.2, 1.2)

plt.legend(loc="best")

plt.subplot(222)

plt.plot(x, y_relu, c="red", label="Relu")

plt.ylim(-1, 6)

plt.legend(loc="best")

plt.subplot(223)

plt.plot(x, y_tanh, c="red", label="Tanh")

plt.ylim(-1.3, 1.3)

plt.legend(loc="best")

plt.subplot(224)

plt.plot(x, y_softplus, c="red", label="Softplus")

plt.ylim(-1, 6)

plt.legend(loc="best")

# 显示图像

plt.show()

#关闭会话

sess.close()

深度学习的三大模型

CNNConvolution Neural Network卷积神经网络

RNNRecurrent Neural Network循环神经网络

DBNDeep Belief Network深度信念网络

实现CNN(Convolution Neural Network)卷积神经网络

import numpy as np

import tensorflow as tf

# 下载并载入 MNIST 手写数字库(55000张28*28像素的图片)

from tensorflow.examples.tutorials.mnist import input_data

# mnist_data可自定义的数据存储目录one_hot是独热码的编码形式0-9的表示形式为0: 1000000000, 1: 0100000000...

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

# None 表示张量(Tensor)的第一个维度可以是任何长度

input_x = tf.placeholder(tf.float32, [None, 28 * 28]) / 255 # 除255是因为有0-255的灰度值

output_y = tf.placeholder(tf.int32, [None, 10]) # 输出: 10个数字的标签

input_x_images = tf.reshape(input_x, [-1, 28, 28 ,1]) # 改变形状之后的输入

# 从 Test测试数据集中选取3000全手写数字的图片和对应标签

test_x = mnist.test.images[:3000] # 图片

test_y = mnist.test.labels[:3000] # 标签

# 构建卷积神经网络

# 第 1 层卷积

# output_size =1+ (input_size+2*padding-kernel_size)/stride

conv1 = tf.layers.conv2d(

inputs=input_x_images, # 形状 [28, 28, 1]

filters=32,            # 32个过滤器输出的深度是32

kernel_size=[5, 5],    # 过滤器在二维的大小是5 * 5

strides=1,             # 步长是1

padding='same',        # same表示输出的大小不变需要在外围补0需补0两圈

activation=tf.nn.relu  # 激活函数使用 Relu

) # 形状 [28, 28, 32]

# 第 1 层池化亚采样

pool1 = tf.layers.max_pooling2d(

inputs=conv1,          # 形状 [28, 28, 32]

pool_size=[2, 2],      # 过滤器在二维的大小是2 * 2

strides=2,             # 步长是2

) # 形状 [14, 14, 32]

# 第 2 层卷积

conv2 = tf.layers.conv2d(

inputs=pool1,          # 形状 [14, 14, 32]

filters=64,            # 64个过滤器输出的深度是64

kernel_size=[5, 5],    # 过滤器在二维的大小是5 * 5

strides=1,             # 步长是1

padding='same',        # same表示输出的大小不变需要在外围补0需补0两圈

activation=tf.nn.relu  # 激活函数使用 Relu

) # 形状 [14, 14, 64]

# 第 2 层池化亚采样

pool2 = tf.layers.max_pooling2d(

inputs=conv2,          # 形状 [14, 14, 64]

pool_size=[2, 2],      # 过滤器在二维的大小是2 * 2

strides=2,             # 步长是2

) # 形状 [7, 7, 64]

# 平坦化Flat

flat = tf.reshape(pool2, [-1, 7 * 7 * 64]) # 形状 7 * 7 * 64

# 1024 个神经元的全连接层

dense = tf.layers.dense(inputs=flat, units=1024, activation=tf.nn.relu)

# Dropout: 丢弃 50%, rate=0.5

dropout = tf.layers.dropout(inputs=dense, rate=0.5)

# 10 个神经元的全连接层此处无需激活函数来做非线性化

logits = tf.layers.dense(inputs=dropout, units=10) # 输入形状 1 * 1 * 10

# 计算误差计算 Cross entropy交叉熵再用Softmax计算百分比概率

loss = tf.losses.softmax_cross_entropy(

onehot_labels=output_y,

logits=logits

)

# Adam优化器来最小化误差学习率0.001

train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

# 精度计算预测值和实际标签的匹配程度

# 返回(accuracy, update_op),会创建两个局部变量

accuracy = tf.metrics.accuracy(

labels=tf.argmax(output_y, axis=1),

predictions=tf.argmax(logits, axis=1),)[1]

# 创建会话

sess = tf.Session()

# 初始化全局变量和局部变量

init = tf.group(tf.global_variables_initializer(),tf.local_variables_initializer())

sess.run(init)

for i in range(20000):

batch = mnist.train.next_batch(50) # 从 Train训练数据集取一组50个样本

train_loss, train_op_ = sess.run([loss, train_op], {input_x: batch[0], output_y: batch[1]})

if i % 100 == 0:

test_accuracy = sess.run(accuracy, {input_x: test_x, output_y: test_y})

print("Step=%d, Train loss=%.4f, [Test accuracy=%.2f]" % (i, train_loss, test_accuracy))

# 测试打印20个预测值和真实值对

test_output = sess.run(logits, {input_x: test_x[:20]})

inferenced_y = np.argmax(test_output, 1)

print(inferenced_y, 'Inferenced numbers') # 推测的数字

print(np.argmax(test_y[:20], 1), 'Real numbers') # 真实的数字

训练结果如下Step=0, Train loss=2.3087, [Test accuracy=0.22]

Step=100, Train loss=0.1605, [Test accuracy=0.57]

...

Step=19800, Train loss=0.0000, [Test accuracy=0.98]

Step=19900, Train loss=0.0067, [Test accuracy=0.98]

[7 2 1 0 4 1 4 9 5 9 0 6 9 0 1 5 9 7 3 4] Inferenced numbers

[7 2 1 0 4 1 4 9 5 9 0 6 9 0 1 5 9 7 3 4] Real numbers

RNN-LSTM循环神经网络

RNN问题梯度消失、梯度爆炸

LSTM: Long Short-Term Memory

LSTM神经元的“三重门”机制

PTB数据集

wget http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz

本例中使用data文件夹下的ptb.test.txtptb.train.txtptb.valid.txt三个文件

utils.pyimport os, sys

import argparse

import datetime

import collections

import numpy as np

import tensorflow as tf

"""

==== 超参数Hyper parameter====

init_scale : 权重参数Weights的初始取值跨度一开始取小一些比较利于训练

learning_rate : 学习率训练时初始为 1.0

num_layers : LSTM 层的数目默认是 2

num_steps : LSTM 展开的步step数相当于每个批次输入单词的数目默认是 35

hidden_size : LSTM 层的神经元数目也是词向量的维度默认是 650

max_lr_epoch : 用初始学习率训练的 Epoch 数目默认是 10

dropout : 在 Dropout 层的留存率默认是 0.5

lr_decay : 在过了 max_lr_epoch 之后每一个 Epoch 的学习率的衰减率训练时初始为 0.93。让学习率逐渐衰减是提高训练效率的有效方法

batch_size : 批次(样本)数目。一次迭代Forword 运算用于得到损失函数以及 BackPropagation 运算用于更新神经网络参数所用的样本数目

batch_size 默认是 20。取比较小的 batch_size 更有利于 Stochastic Gradient Descent随机梯度下降防止被困在局部最小值

"""

# 数据集目录

data_path = "/Users/alan/Desktop/demo/simple-examples/data"

# 保存训练所得的模型参数文件的目录

save_path = "./save"

# 测试时读取模型参数文件的名称

load_file = "train-checkpoint-69"

parser = argparse.ArgumentParser()

parser.add_argument('--data_path', type=str, default=data_path, help='Path to data for training and testing')

parser.add_argument('--load_file', type=str, default=load_file, help='Path to checkpoint file of model variables during training')

args = parser.parse_args()

# 判断是否 Python3 版本

Py3 = sys.version_info[0] == 3

# 将文件根据语句结束标识符()来分割

def read_words(filename):

with tf.gfile.GFile(filename, "r") as f:

if Py3:

return f.read().replace("\n", "").split()

else:

return f.read().decode("utf-8").replace("\n", "").split()

# 构造从单词到唯一整数值的映射

def build_vocab(filename):

data = read_words(filename)

# 用counter统计单词出现次数并进行排序如the最多对应整数为0依此类推

counter = collections.Counter(data)

count_pairs = sorted(counter.items(), key= lambda x: (-x[1], x[0]))

words, _ = list(zip(*count_pairs))

# 单词到整数的映射

word_to_id = dict(zip(words, range(len(words))))

return word_to_id

# 将文件里的单词都替换成独一的整数

def file_to_word_ids(filename, word_to_id):

data = read_words(filename)

return [word_to_id[word] for word in data if word in word_to_id]

# 加载所有数据读取所有单词把将转成唯一对应的整数值

def load_data(data_path):

# 三个数据集的路径

train_path = os.path.join(data_path, "ptb.train.txt")

valid_path = os.path.join(data_path, "ptb.valid.txt")

test_path = os.path.join(data_path, "ptb.test.txt")

# 建立词汇表将所有单词转为唯一对应的整数值

word_to_id = build_vocab(train_path)

train_data = file_to_word_ids(train_path, word_to_id)

valid_data = file_to_word_ids(valid_path, word_to_id)

test_data = file_to_word_ids(test_path, word_to_id)

# 所胡独五词汇的个数

vocab_size = len(word_to_id)

# 反转一个词汇表以便之后从整数转为单词

id_to_word = dict(zip(word_to_id.values(), word_to_id.keys()))

print(word_to_id)

print("=====================")

print(vocab_size)

print("=====================")

print(train_data[:10])

print("=====================")

print(" ".join([id_to_word[x] for x in train_data[:10]]))

return train_data, valid_data, test_data, vocab_size, id_to_word

# 生成批次样本

def generate_batches(raw_data, batch_size, num_steps):

# 将数据转为 Tensor 类型

raw_data = tf.convert_to_tensor(raw_data, name="raw_data", dtype=tf.int32)

data_len = tf.size(raw_data)

batch_len = data_len // batch_size

# 将数据形状转为 [batch_size, batch_len]

data = tf.reshape(raw_data[0: batch_size * batch_len],

[batch_size, batch_len])

epoch_size = (batch_len - 1) // num_steps

# range_input_producer 可以用多线程异步的方式从数据集里提取数据

# 用多线程可以加快训练因为 feed_dict 的赋值方式效率不高

# shuffle 为 False 表示不打乱数据而按照队列先进先出的方式提取数据

i = tf.train.range_input_producer(epoch_size, shuffle=False).dequeue()

# 假设一句话是这样 “我爱我的祖国和人民”

# 那么如果 x 是类似这样 “我爱我的祖国”

x = data[:, i * num_steps:(i + 1) * num_steps]

x.set_shape([batch_size, num_steps])

# y 就是类似这样正好是 x 的时间步长 + 1 “爱我的祖国和”

# 因为我们的模型就是要预测一句话中每一个单词的下一个单词

# 当然这边的例子很简单实际的数据不止一个维度

y = data[:, i * num_steps + 1: (i + 1) * num_steps + 1]

y.set_shape([batch_size, num_steps])

return x, y

# 输入数据

class Input(object):

def __init__(self, batch_size, num_steps, data):

self.batch_size = batch_size

self.num_steps = num_steps

self.epoch_size = ((len(data) // batch_size) - 1) // num_steps

# input_data 是输入targets 是期望的输出

self.input_data, self.targets = generate_batches(data, batch_size, num_steps)

network.pyimport tensorflow as tf

# 神经网络的模型

class Model(object):

def __init__(self, input, is_training, hidden_size, vocab_size, num_layers, dropout=0.5, init_scale=0.05):

self.is_training = is_training

self.input_obj = input

self.batch_size = input.batch_size

self.num_steps = input.num_steps

self.hidden_size = hidden_size

# 此处操作和变量用 CPU 来计算暂无 GPU 的实现

with tf.device("/cpu:0"):

# 创建 词向量Word EmbeddingEmbedding 表示 Dense Vector密集向量

# 词向量本质上是一种单词聚类Clustering的方法

embedding = tf.Variable(tf.random_uniform([vocab_size, self.hidden_size], -init_scale, init_scale))

inputs = tf.nn.embedding_lookup(embedding, self.input_obj.input_data)

# 如果是训练并且dropout率小于1使输入经过一个Dropout层

# Dropout 防止过拟合

if is_training and dropout 

inputs = tf.nn.dropout(inputs, dropout)

# 状态state的存储和提取

# 第二维是 2 是因为对每一个 LSTM 单元有两个来自上一单元的输入

# 一个是 前一时刻 LSTM 的输出 h(t-1)

# 一个是 前一时刻的单元状态 C(t-1)

# 这个 C 和 h 是用于构建之后的 tf.contrib.rnn.LSTMStateTuple

self.init_state = tf.placeholder(tf.float32, [num_layers, 2, self.batch_size, self.hidden_size])

# 每一层的状态

state_per_layer_list = tf.unstack(self.init_state, axis=0)

# 初始的状态包含 前一时刻 LSTM 的输出 h(t-1) 和 前一时刻的单元状态 C(t-1)用于之后的 dynamic_rnn

rnn_tuple_state = tuple(

[tf.contrib.rnn.LSTMStateTuple(state_per_layer_list[idx][0], state_per_layer_list[idx][1]) for idx in range(num_layers)]

)

# 创建一个 LSTM 层其中的神经元数目是 hidden_size 个默认 650 个

cell = tf.contrib.rnn.LSTMCell(hidden_size)

# 如果是训练时 并且 Dropout 率小于 1给 LSTM 层加上 Dropout 操作

# 这里只给 输出 加了 Dropout 操作留存率(output_keep_prob)是 0.5

# 输入则是默认的 1所以相当于输入没有做 Dropout 操作

if is_training and dropout 

cell = tf.contrib.rnn.DropoutWrapper(cell, output_keep_prob=dropout)

# 如果 LSTM 的层数大于 1, 则总计创建 num_layers 个 LSTM 层

# 并将所有的 LSTM 层包装进 MultiRNNCell 这样的序列化层级模型中

# state_is_tuple=True 表示接受 LSTMStateTuple 形式的输入状态

if num_layers > 1:

cell = tf.contrib.rnn.MultiRNNCell([cell for _ in range(num_layers)],

state_is_tuple=True)

# dynamic_rnn动态 RNN让不同迭代传入的 Batch 可以是长度不同的数据

# 但同一次迭代中一个 Batch 内部的所有数据长度仍然是固定的

# dynamic_rnn 能更好处理 padding补零的情况节约计算资源

# 返回两个变量

# 第一个是一个 Batch 里在时间维度默认是 35上展开的所有 LSTM 单元的输出形状默认为 [20, 35, 650]之后会经过扁平层处理

# 第二个是最终的 state状态包含 当前时刻 LSTM 的输出 h(t) 和 当前时刻的单元状态 C(t)

output, self.state = tf.nn.dynamic_rnn(cell, inputs, dtype=tf.float32, initial_state=rnn_tuple_state)

# 扁平化处理改变输出形状为 (batch_size * num_steps, hidden_size)形状默认为 [700, 650]

output = tf.reshape(output, [-1, hidden_size]) # -1 表示自动推导维度大小

# Softmax的权重

softmax_w = tf.Variable(tf.random_uniform([hidden_size, vocab_size], -init_scale, init_scale))

# Softmax的偏置

softmax_b = tf.Variable(tf.random_uniform([vocab_size], -init_scale, init_scale))

# logits 是 Logistic Regression用于分类模型线性方程 y = W * x + b 计算的结果分值

# 这个 logits分值之后会用 Softmax 来转成百分比概率

# output 是输入x softmax_w 是 权重Wsoftmax_b 是偏置b

# 返回 W * x + b 结果

logits = tf.nn.xw_plus_b(output, softmax_w, softmax_b)

# 将 logits 转化为三维的 Tensor为了 sequence loss 的计算

# 形状默认为 [20, 35, 10000]

logits = tf.reshape(logits, [self.batch_size, self.num_steps, vocab_size])

# 计算 logits 的序列的交叉熵Cross-Entropy的损失loss

loss = tf.contrib.seq2seq.sequence_loss(

logits, # 形状默认为 [20, 35, 10000]

self.input_obj.targets, # 期望输出形状默认为 [20, 35]

tf.ones([self.batch_size, self.num_steps], dtype=tf.float32),

average_across_timesteps=False,

average_across_batch=True

)

# 更新代价Cost

self.cost = tf.reduce_sum(loss)

# Softmax算出来的概率

self.softmax_out = tf.nn.softmax(tf.reshape(logits, [-1, vocab_size]))

# 取最大概率的那个值作为预测

self.predict = tf.cast(tf.argmax(self.softmax_out, axis=1), tf.int32)

# 预测值和真实值目标对比

correct_prediction = tf.equal(self.predict, tf.reshape(self.input_obj.targets, [-1]))

# 计算预测的精度

self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 如果是 测试则直接退出

if not is_training:

return

# 学习率,trainable=False表示“不可被训练”

self.learning_rate = tf.Variable(0.0, trainable=False)

# 返回所有可被训练trainable=True。如果不设定 trainable=False默认的 Variable 都是可以被训练的

# 也就是除了不可被训练的 学习率 之外的其他变量

tvars = tf.trainable_variables()

# tf.clip_by_global_norm实现 Gradient Clipping梯度裁剪是为了防止梯度爆炸

# tf.gradients 计算 self.cost 对于 tvars 的梯度求导返回一个梯度的列表

grads, _ = tf.clip_by_global_norm(tf.gradients(self.cost, tvars), 5)

# 优化器用 GradientDescentOptimizer梯度下降优化器

optimizer = tf.train.GradientDescentOptimizer(self.learning_rate)

# apply_gradients应用梯度将之前用Gradient Clipping梯度裁剪过的梯度 应用到可被训练的变量上去做梯度下降

# apply_gradients 其实是 minimize 方法里面的第二步第一步是 计算梯度

self.train_op = optimizer.apply_gradients(

zip(grads, tvars),

global_step=tf.train.get_or_create_global_step()

)

# 用于更新学习率

self.new_lr = tf.placeholder(tf.float32, shape=[])

self.lr_update = tf.assign(self.learning_rate, self.new_lr)

# 更新 学习率

def assign_lr(self, session, lr_value):

session.run(self.lr_update, feed_dict={self.new_lr: lr_value})

train.py"""

训练神经网络模型

大家之后可以加上各种的 name_scope命名空间

用 TensorBoard 来可视化

==== 一些术语的概念 ====

# Batch size : 批次(样本)数目。一次迭代Forword 运算用于得到损失函数以及 BackPropagation 运算用于更新神经网络参数所用的样本数目。Batch size 越大所需的内存就越大

# Iteration : 迭代。每一次迭代更新一次权重网络参数每一次权重更新需要 Batch size 个数据进行 Forward 运算再进行 BP 运算

# Epoch : 纪元/时代。所有的训练样本完成一次迭代

# 假如 : 训练集有 1000 个样本Batch_size=10

# 那么 : 训练完整个样本集需要 100 次 Iteration1 个 Epoch

# 但一般我们都不止训练一个 Epoch

==== 超参数Hyper parameter====

init_scale : 权重参数Weights的初始取值跨度一开始取小一些比较利于训练

learning_rate : 学习率训练时初始为 1.0

num_layers : LSTM 层的数目默认是 2

num_steps : LSTM 展开的步step数相当于每个批次输入单词的数目默认是 35

hidden_size : LSTM 层的神经元数目也是词向量的维度默认是 650

max_lr_epoch : 用初始学习率训练的 Epoch 数目默认是 10

dropout : 在 Dropout 层的留存率默认是 0.5

lr_decay : 在过了 max_lr_epoch 之后每一个 Epoch 的学习率的衰减率训练时初始为 0.93。让学习率逐渐衰减是提高训练效率的有效方法

batch_size : 批次(样本)数目。一次迭代Forword 运算用于得到损失函数以及 BackPropagation 运算用于更新神经网络参数所用的样本数目

batch_size 默认是 20。取比较小的 batch_size 更有利于 Stochastic Gradient Descent随机梯度下降防止被困在局部最小值

"""

from utils import *

from network import *

def train(train_data, vocab_size, num_layers, num_epochs, batch_size, model_save_name,

learning_rate=1.0, max_lr_epoch=10, lr_decay=0.93, print_iter=50):

# 训练的输入

training_input = Input(batch_size=batch_size, num_steps=35, data=train_data)

# 创建训练的模型

m = Model(training_input, is_training=True, hidden_size=650, vocab_size=vocab_size, num_layers=num_layers)

# 初始化变量的操作

init_op = tf.global_variables_initializer()

# 初始的学习率learning rate的衰减率

orig_decay = lr_decay

with tf.Session() as sess:

sess.run(init_op)  # 初始化所有变量

# Coordinator协调器用于协调线程的运行

coord = tf.train.Coordinator()

# 启动线程

threads = tf.train.start_queue_runners(coord=coord)

# 为了用 Saver 来保存模型的变量

saver = tf.train.Saver() # max_to_keep 默认是 5, 只保存最近的 5 个模型参数文件

# 开始 Epoch 的训练

for epoch in range(num_epochs):

# 只有 Epoch 数大于 max_lr_epoch设置为 10后才会使学习率衰减

# 也就是说前 10 个 Epoch 的学习率一直是 1, 之后每个 Epoch 学习率都会衰减

new_lr_decay = orig_decay ** max(epoch + 1 - max_lr_epoch, 0)

m.assign_lr(sess, learning_rate * new_lr_decay)

# 当前的状态

# 第二维是 2 是因为对每一个 LSTM 单元有两个来自上一单元的输入

# 一个是 前一时刻 LSTM 的输出 h(t-1)

# 一个是 前一时刻的单元状态 C(t-1)

current_state = np.zeros((num_layers, 2, batch_size, m.hidden_size))

# 获取当前时间以便打印日志时用

curr_time = datetime.datetime.now()

for step in range(training_input.epoch_size):

# train_op 操作计算被修剪clipping过的梯度并最小化 cost误差

# state 操作返回时间维度上展开的最后 LSTM 单元的输出C(t) 和 h(t)作为下一个 Batch 的输入状态

if step % print_iter != 0:

cost, _, current_state = sess.run([m.cost, m.train_op, m.state], feed_dict={m.init_state: current_state})

else:

seconds = (float((datetime.datetime.now() - curr_time).seconds) / print_iter)

curr_time = datetime.datetime.now()

cost, _, current_state, acc = sess.run([m.cost, m.train_op, m.state, m.accuracy], feed_dict={m.init_state: current_state})

# 每 print_iter默认是 50打印当下的 Cost误差/损失和 Accuracy精度

print("Epoch {}, 第 {} 步, 损失: {:.3f}, 精度: {:.3f}, 每步所用秒数: {:.2f}".format(epoch, step, cost, acc, seconds))

# 保存一个模型的变量的 checkpoint 文件

saver.save(sess, save_path + '/' + model_save_name, global_step=epoch)

# 对模型做一次总的保存

saver.save(sess, save_path + '/' + model_save_name + '-final')

# 关闭线程

coord.request_stop()

coord.join(threads)

if __name__ == "__main__":

if args.data_path:

data_path = args.data_path

train_data, valid_data, test_data, vocab_size, id_to_word = load_data(data_path)

train(train_data, vocab_size, num_layers=2, num_epochs=70, batch_size=20,

model_save_name='train-checkpoint')

if __name__ == "__main__":

if args.data_path:

data_path = args.data_path

train_data, valid_data, test_data, vocab_size, id_to_word = load_data(data_path)

train(train_data, vocab_size, num_layers=2, num_epochs=70, batch_size=20,

model_save_name='train-checkpoint')

test.pyfrom utils import *

from network import *

def test(model_path, test_data, vocab_size, id_to_word):

# 测试的输入

test_input = Input(batch_size=20, num_steps=35, data=test_data)

# 创建测试的模型基本的超参数需要和训练时用的一致例如

# hidden_sizenum_stepsnum_layersvocab_sizebatch_size 等等

# 因为我们要载入训练时保存的参数的文件如果超参数不匹配 TensorFlow 会报错

m = Model(test_input, is_training=False, hidden_size=650, vocab_size=vocab_size, num_layers=2)

# 为了用 Saver 来恢复训练时生成的模型的变量

saver = tf.train.Saver()

with tf.Session() as sess:

# Coordinator协调器用于协调线程的运行

coord = tf.train.Coordinator()

# 启动线程

threads = tf.train.start_queue_runners(coord=coord)

# 当前的状态

# 第二维是 2 是因为测试时指定只有 2 层 LSTM

# 第二维是 2 是因为对每一个 LSTM 单元有两个来自上一单元的输入

# 一个是 前一时刻 LSTM 的输出 h(t-1)

# 一个是 前一时刻的单元状态 C(t-1)

current_state = np.zeros((2, 2, m.batch_size, m.hidden_size))

# 恢复被训练的模型的变量

saver.restore(sess, model_path)

# 测试30个批次

num_acc_batches = 30

# 打印预测单词和实际单词的批次数

check_batch_idx = 25

# 超过5个批次才开始累加精度

acc_check_thresh = 5

# 初始精度的和用于之后算平均精度

accuracy = 0

for batch in range(num_acc_batches):

if batch == check_batch_idx:

true, pred, current_state, acc = sess.run([m.input_obj.targets, m.predict, m.state, m.accuracy],

feed_dict={m.init_state: current_state})

pred_words = [id_to_word[x] for x in pred[:m.num_steps]]

true_words = [id_to_word[x] for x in true[0]]

print("True words (1st line) vs. predicted words (2nd line)")

print(" ".join(true_words)) # 真实的单词

print(" ".join(pred_words)) # 预测的单词

else:

acc, current_state = sess.run([m.accuracy, m.state],feed_dict={m.init_state: current_state})

if batch >= accuracy:

accuracy += acc

# 打印平均精度

print("Average accuracy: {:.3f}".format(accuracy / (num_acc_batches - acc_check_thresh)))

# 关闭线程

coord.request_stop()

coord.join(threads)

if __name__ == "__main__":

if args.data_path:

data_path = args.data_path

if args.load_file:

load_file = args.load_file

train_data, valid_data, test_data, vocab_size, id_to_word = load_data(data_path)

trained_model = save_path + '/' + load_file

test(trained_model, test_data, vocab_size, id_to_word)

在Mac上进行一次训练需耗时30多分钟写这篇文章时训练仍在进行以下是第二次训练完成后执行test.py的结果可以看到精确度还是很低的

True words (1st line) vs. predicted words (2nd line)

stock market is headed many traders were afraid to trust stock prices quoted on the big board the futures halt was even by big board floor traders it things up said

is market is n't by of said to be prices at a dollar board the dollar index that a a in a board in in said the is a that a

Average accuracy: 0.236

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值