基于Google Colab的
tensorflow 1.8+深度学习教程
今天是2019年5月10号,小亮最近折腾了两天,主要基于Google Colab实现了一下tensorflow 1.8的基础教程,至于说为什么基于Google Colab,大家可以看我上一篇博文:Deep Learning时代最好用的云GPU——Google Colab (免费提供 Tesla T4 GPU) 话不多说,我们进入今天的课堂!如果你对NLP,对深度学习感兴趣,欢迎和小亮交流,联系方式如下。
笔者信息:Next_Legend QQ:1219154092 机器学习 自然语言处理 深度学习 统计概率论
小亮的博客:https://legendtianjin.github.io/NextLegend.github.io/ ——2019.5.10于北洋
一、为什么是基于tensorflow 1.8?
这是因为tensorflow 1.8版本是一个分水岭!!!什么分水岭呢?(先别着急,答案在后面。)2018 年 3 月 30 日,Google 在加州山景城举行了第二届 TensorFlow Dev Summit 开发者峰会,并宣布正式发布 TensorFlow 1.8 版本。这一具有里程碑式意义的新版本发布。众多新功能的加入和支持展示了 TensorFlow 的雄心壮志,同时早在 2017 年秋就开始测试的Eager Execution(动态图机制)在这一版本中终于正式加入,并成为了入门 TensorFlow 的官方推荐模式。
The easiest way to get started with TensorFlow is using Eager Execution. ——https://www.tensorflow.org/tutorials
在此之前,TensorFlow 所基于的传统 Graph Execution 的弊端,如入门门槛高、调试困难、灵活性差、无法使用 Python 原生控制语句等早已被开发者诟病许久。一些新的基于动态图机制的深度学习框架(如 PyTorch)也横空出世,并以其易用性和快速开发的特性而占据了一席之地。尤其是在学术研究等需要快速迭代模型的领域,PyTorch 等新兴深度学习框架已经成为主流。然而,目前市面上相关的 TensorFlow 相关的中文技术书籍及资料仍然基于传统的 Graph Execution 模式,让不少初学者(尤其是大学生)望而却步。由此,在 TensorFlow 正式支持 Eager Execution 之际,有必要重点介绍一下Eager Execution(动态图机制,帮助初学者及需要快速迭代模型的研究者,以一个全新的角度快速入门 TensorFlow。
二、tensorflow 1.8+ 参考教程
小亮这里其实也是参考了一些资料,放在这里供大家学习参考。(以下资料小亮均放在私人博客里,欢迎大家前往下载。)
小亮的博客:https://legendtianjin.github.io/NextLegend.github.io/
TensorFlow官网教程
简单粗暴 TensorFlow
2018TensorFlow中文版
2018TensorFlow英文版
三、tensorflow 1.8+基础教程
下面我们就开始tensorflow基础教程的学习!因为tensorflow 每次的更新都会更改很多函数,所以大家不可避免的会遇到很多bug,刚开始要静下心来,慢慢找到问题,在下面的教程中小亮就遇到一个bug,足足想了两天,才解决,切身体会:山穷水尽之时,便是柳暗花明之时!
3.1、基于Google Colab的云GPU配置
虽然Google Colab提供给我们免费的GPU和TPU使用,但是每天免费使用时间为12小时,所以如果我们使用Colab的话,每天的第一件事就是配置相关文件,其实看上去有点麻烦,5秒钟就可以完成相关配置。(步骤如下:)敲入以下代码,会出现一个链接,点击链接然后授权Google账号(没有的话自己注册一个就好),复制粘贴授权码就可以了。(授权的目的是为了使Colab和Google云端硬盘通信,方便数据文件和代码文件的管理。)
from google.colab import drive
drive.mount('/content/drive/')
3.2、查看tensorflow版本号以及安装tensorflow 1.8
为了增加阅读的流畅性,后面小亮尽量使用代码讲解,少一些文字性的描述。大家尽快去尝试,出现问题了先自己解决,然后再请教别人,欢迎大家和小亮交流。
(1)查看tensorflow版本号
import tensorflow as tf
tf.__version__
(2)安装tensorflow 1.8
!pip install tensorflow==1.8.0rc
最后再次查看tensorflow版本号,发现是我们安装的版本
3.3、第一个tensorflow程序
TensorFlow Eager Execution(动态图)模式在TensorFlow 1.8版本中开始引入,相比传统的Graph Execution模式有了很大的进步。该模式能够快速调试,使用Python原生控制语句,能够大大降低学习的门槛。作为未来TensorFlow 2.0版本的默认模式,有必要从现在就开始熟悉。本文作为一个入门简介,将简要介绍TensorFlow安装以及如何使用Eager Execution模式。
import tensorflow as tf
A = tf.constant([[1, 2], [3, 4]])
B = tf.constant([[5, 6], [7, 8]])
C = tf.matmul(A, B)
print(C)
3.4、TensorFlow 自动求导机制来计算导数。
(1)以下代码展示了如何使用 tf.GradientTape() 计算函数 y(x) = x^2 在 x = 3 时的导数。
import tensorflow as tf
x = tf.get_variable('x', shape=[1], initializer=tf.constant_initializer(3.))
with tf.GradientTape() as tape:
y = tf.square(x)
y_grad = tape.gradient(y, x)
print([y.numpy(), y_grad.numpy()])
(2)在机器学习中,更加常见的是对多元函数求偏导数,以及对向量或矩阵的求导。以下代码展示了如何使用 tf.GradientTape() 计算函数 L(w, b) = ∥Xw+bby∥^2 在 w = (1, 2)^T, b = 1 时分别对 w, b 的偏导数。其中 X = [1 2 3 4], y =[1 2 ]
X = tf.constant([[1., 2.], [3., 4.]])
y = tf.constant([[1.], [2.]])
w = tf.get_variable('w', shape=[2, 1], initializer=tf.constant_initializer([[1.], [2.]]))
b = tf.get_variable('b', shape=[1], initializer=tf.constant_initializer([1.]))
with tf.GradientTape() as tape:
L = 0.5 * tf.reduce_sum(tf.square(tf.matmul(X, w) + b - y))
w_grad, b_grad = tape.gradient(L, [w, b])
print([L.numpy(), w_grad.numpy(), b_grad.numpy()])
3.5、基础示例:多层感知机(MLP)
我们从编写一个最简单的 多层感知机 (Multilayer Perceptron, MLP)开始,介绍 TensorFlow 的模型编写 方式。这里,我们使用多层感知机完成 MNIST 手写体数字图片数据集 [LeCun1998] 的分类任务。
import tensorflow as tf
import numpy as np
tf.enable_eager_execution
class DataLoader():
def __init__(self):
mnist = tf.contrib.learn.datasets.load_dataset("mnist")
self.train_data = mnist.train.images
self.train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
self.eval_data = mnist.test.images
self.eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
def get_batch(self, batch_size):
index = np.random.randint(0, np.shape(self.train_data)[0], batch_size)
return self.train_data[index, :], self.train_labels[index]
class MLP(tf.keras.Model):
def __init__(self):
super().__init__()
self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
self.dense2 = tf.keras.layers.Dense(units=10)
def call(self, inputs):
x = self.dense1(inputs)
x = self.dense2(x)
return x
def predict(self, inputs):
logits = self(inputs)
return tf.argmax(logits, axis=-1)
num_batches = 1000
batch_size = 50
learning_rate = 0.001
model = MLP()
data_loader = DataLoader()
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
for batch_index in range(num_batches):
X, y = data_loader.get_batch(batch_size)
with tf.GradientTape() as tape:
y_logit_pred = model(tf.convert_to_tensor(X))
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=y_logit_pred)
print("batch %d: loss %f" % (batch_index, loss.numpy)
grads = tape.gradient(loss, model.variables)
optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
num_eval_samples = np.shape(data_loader.eval_labels)[0]
y_pred = model.predict(data_loader.eval_data).numpy()
print("test accuracy: %f" % (sum(y_pred == data_loader.eval_labels) / num_eval_samples))
3.6、卷积神经网络(CNN)
这里,我们使用卷积神经网络(CNN)完成 MNIST 手写体数字图片数据集 [LeCun1998] 的分类任务。
import tensorflow as tf
import numpy as np
tf.enable_eager_execution?
class DataLoader():
def __init__(self):
mnist = tf.contrib.learn.datasets.load_dataset("mnist")
self.train_data = mnist.train.images
self.train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
self.eval_data = mnist.test.images
self.eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
def get_batch(self, batch_size):
index = np.random.randint(0, np.shape(self.train_data)[0], batch_size)
return self.train_data[index, :], self.train_labels[index]
class CNN(tf.keras.Model):
def __init__(self):
super().__init__()
self.conv1 = tf.keras.layers.Conv2D(
filters=32,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu
)
self.pool1 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)
self.conv2 = tf.keras.layers.Conv2D(
filters=64,
kernel_size=[5, 5],padding="same",activation=tf.nn.relu)
self.pool2 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)
self.flatten = tf.keras.layers.Reshape(target_shape=(7 * 7 * 64,))
self.dense1 = tf.keras.layers.Dense(units=1024, activation=tf.nn.relu)
self.dense2 = tf.keras.layers.Dense(units=10)
def call(self, inputs):
inputs = tf.reshape(inputs, [-1, 28, 28, 1])
x = self.conv1(inputs)
x = self.pool1(x)
x = self.conv2(x)
x = self.pool2(x)
x = self.flatten(x)
x = self.dense1(x)
x = self.dense2(x)
return x
def predict(self, inputs):
logits = self(inputs)
return tf.argmax(logits, axis=-1)
num_batches = 100
batch_size = 50
learning_rate = 0.001
model = CNN()
data_loader = DataLoader()
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
for batch_index in range(num_batches):
X, y = data_loader.get_batch(batch_size)
with tf.GradientTape() as tape:
y_logit_pred = model(tf.convert_to_tensor(X))
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=y_logit_pred)
print("batch %d: loss %f" % (batch_index, loss.numpy()))
grads = tape.gradient(loss, model.variables)
optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
num_eval_samples = np.shape(data_loader.eval_labels)[0]
y_pred = model.predict(data_loader.eval_data).numpy()
print("test accuracy: %f" % (sum(y_pred == data_loader.eval_labels) / num_eval_samples))
3.7、循环神经网络(RNN)
循环神经网络(Recurrent Neural Network, RNN)是一种适宜于处理序列数据的神经网络,被广泛用于语言模型、文本生成、机器翻译等。这里,我们使用 RNN 来进行尼采风格文本的自动生成。这个任务的本质其实预测一段英文文本的接续字母的概率分布。
import tensorflow as tf
import numpy as np
tf.enable_eager_execution
class DataLoader():
def __init__(self):
path = tf.keras.utils.get_file('nietzsche.txt',
origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt')
with open(path, encoding='utf-8') as f:
self.raw_text = f.read().lower()
self.chars = sorted(list(set(self.raw_text)))
self.char_indices = dict((c, i) for i, c in enumerate(self.chars))
self.indices_char = dict((i, c) for i, c in enumerate(self.chars))
self.text = [self.char_indices[c] for c in self.raw_text]
def get_batch(self, seq_length, batch_size):
seq = []
next_char = []
for i in range(batch_size):
index = np.random.randint(0, len(self.text) - seq_length)
seq.append(self.text[index:index + seq_length])
next_char.append(self.text[index + seq_length])
return np.array(seq), np.array(next_char)
class RNN(tf.keras.Model):
def __init__(self, num_chars):
super().__init__()
self.num_chars = num_chars
self.cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=256)
self.dense = tf.keras.layers.Dense(units=self.num_chars)
def predict(self, inputs, temperature=1.):
batch_size, _ = tf.shape(inputs)
logits = self(inputs)
prob = tf.nn.softmax(logits / temperature).numpy()
return np.array([np.random.choice(self.num_chars, p=prob[i, :])
for i in range(batch_size.numpy())])
def call(self, inputs):
batch_size, seq_length = tf.shape(inputs)
inputs = tf.one_hot(inputs, depth=self.num_chars)
state = self.cell.zero_state(batch_size=batch_size, dtype=tf.float32)
for t in range(seq_length.numpy()):
output, state = self.cell(inputs[:, t, :], state)
output = self.dense(output)
return output
num_batches = 3000
batch_size = 50
seq_length = 20
learning_rate = 0.001
data_loader = DataLoader()
model = RNN(len(data_loader.chars))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
for batch_index in range(num_batches):
X, y = data_loader.get_batch(seq_length, batch_size)
with tf.GradientTape() as tape:
y_logit_pred = model(X)
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=y_logit_pred)
print("batch %d: loss %f" % (batch_index, loss.numpy()))
grads = tape.gradient(loss, model.variables)
optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
X_, _ = data_loader.get_batch(5, 1)
for diversity in [0.2, 0.5, 1.0, 1.2]:
X = X_
print("diversity %f:" % diversity)
for t in range(400):
y_pred = model.predict(X,diversity)
print(data_loader.indices_char[y_pred[0]], end='', flush=True)
X = np.concatenate([X[:, 1:], np.expand_dims(y_pred, axis=1)], axis=-1)
3.8、深度强化学习(DRL)
强化学习 (Reinforcement learning,RL)强调如何基于环境而行动,以取得最大化的预期利益。结合了深度学习技术后的强化学习更是如虎添翼。这两年广为人知的 AlphaGo 即是深度强化学习的典型应用。这里,我们使用深度强化学习玩 CartPole(平衡杆)游戏。简单说,我们需要让模型控制杆的左右运动,以让其一直保持竖直平衡状态。
import gym
env = gym.make("CartPole-v1")
observation = env.reset()
for _ in range(1000):
env.render()
action = env.action_space.sample()
observation, reward, done, info = env.step(action)
if done:
observation = env.reset()
env.close()