- ?
如何利用TensorFlow.js部署简单的AI版「你画我猜」图像识别应用
Thalia
展开
选自Medium,作者:Zaid Alyafeai,机器之心编译,参与:Geek AI、路。
本文创建了一个简单的工具来识别手绘图像,并且输出当前图像的名称。该应用无需安装任何额外的插件,可直接在浏览器上运行。作者使用谷歌 Colab 来训练模型,并使用 TensorFlow.js 将它部署到浏览器上。
代码和 demo
demo 地址:https://zaidalyafeai.github.io/sketcher/代码地址:https://github/zaidalyafeai/zaidalyafeai.github.io/tree/master/sketcher请通过以下链接在谷歌 Colab 上测试自己的 notebook:https://colab.research.google/github/zaidalyafeai/zaidalyafeai.github.io/blob/master/sketcher/Sketcher.ipynb
数据集
我们将使用卷积神经网络(CNN)来识别不同类型的手绘图像。这个卷积神经网络将在 Quick Draw 数据集(https://github/googlecreativelab/quickdraw-dataset)上接受训练。该数据集包含 345 个类别的大约 5 千万张手绘图像。
部分图像类别
流程
我们将使用 Keras 框架在谷歌 Colab 免费提供的 GPU 上训练模型,然后使用 TensorFlow.js 直接在浏览器上运行模型。我在 TensorFlow.js 上创建了一个教程(https://medium/tensorflow/a-gentle-introduction-to-tensorflow-js-dba2e5257702)。在继续下面的工作之前,请务必先阅读一下这个教程。下图为该项目的处理流程:
流程
在 Colab 上进行训练
谷歌 Colab 为我们提供了免费的 GPU 处理能力。你可以阅读下面的教程(https://medium/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d)了解如何创建 notebook 和开始进行 GPU 编程。
导入
我们将使用以 TensorFlow 作为后端、Keras 作为前端的编程框架
import os
import glob
import numpy as np
from tensorflow.keras import layers
from tensorflow import keras
import tensorflow as tf
加载数据
由于内存容量有限,我们不会使用所有类别的图像进行训练。我们仅使用数据集中的 100 个类别(https://raw.githubusercontent/zaidalyafeai/zaidalyafeai.github.io/master/sketcher/mini_classes.txt)。每个类别的数据可以在谷歌 Colab(https://console.cloud.google/storage/browser/quickdrawdataset/full/numpybitmap?pli=1)上以 NumPy 数组的形式获得,数组的大小为 [N, 784],其中 N 为某类图像的数量。我们首先下载这个数据集:
import urllib.request
def download():
base = 'https://storage.googleapis/quickdraw_dataset/full/numpy_bitmap/'
for c in classes:
cls_url = c.replace('_', '%20')
path = base+cls_url+'.npy'
print(path)
urllib.request.urlretrieve(path, 'data/'+c+'.npy')
由于内存限制,我们在这里将每类图像仅仅加载 5000 张。我们还将留出其中的 20% 作为测试数据。
def load_data(root, vfold_ratio=0.2, max_items_per_class= 5000 ):
all_files = glob.glob(os.path.join(root, '*.npy'))
#initialize variables
x = np.empty([0, 784])
y = np.empty([0])
class_names = []
#load a subset of the data to memory
for idx, file in enumerate(all_files):
data = np.load(file)
data = data[0: max_items_per_class, :]
labels = np.full(data.shape[0], idx)
x = np.concatenate((x, data), axis=0)
y = np.append(y, labels)
class_name, ext = os.path.splitext(os.path.basename(file))
class_names.append(class_name)
data = None
labels = None
#separate into training and testing
permutation = np.random.permutation(y.shape[0])
x = x[permutation, :]
y = y[permutation]
vfold_size = int(x.shape[0]/100*(vfold_ratio*100))
x_test = x[0:vfold_size, :]
y_test = y[0:vfold_size]
x_train = x[vfold_size:x.shape[0], :]
y_train = y[vfold_size:y.shape[0]]
return x_train, y_train, x_test, y_test, class_names
数据预处理
我们对数据进行预处理操作,为训练模型做准备。该模型将使用规模为 [N, 28, 28, 1] 的批处理,并且输出规模为 [N, 100] 的概率。
# Reshape and normalize
x_train = x_train.reshape(x_train.shape[0], image_size, image_size, 1).astype('float32')
x_test = x_test.reshape(x_test.shape[0], image_size, image_size, 1).astype('float32')
x_train /= 255.0
x_test /= 255.0
# Convert class vectors to class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
创建模型
我们将创建一个简单的卷积神经网络。请注意,模型越简单、参数越少越好。实际上,我们将把模型转换到浏览器上然后再运行,并希望模型能在预测任务中快速运行。下面的模型包含 3 个卷积层和 2 个全连接层:
# Define model
model = keras.Sequential()
model.add(layers.Convolution2D(16, (3, 3),
padding='same',
input_shape=x_train.shape[1:], activation='relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Convolution2D(32, (3, 3), padding='same', activation= 'relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Convolution2D(64, (3, 3), padding='same', activation= 'relu'))
model.add(layers.MaxPooling2D(pool_size =(2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(100, activation='softmax'))
# Train model
adam = tf.train.AdamOptimizer()
modelpile(loss='categorical_crossentropy',
optimizer=adam,
metrics=['top_k_categorical_accuracy'])
print(model.summary())
拟合、验证及测试
在这之后我们对模型进行了 5 轮训练,将训练数据分成了 256 批输入模型,并且分离出 10% 作为验证集。
#fit the model
model.fit(x = x_train, y = y_train, validation_split=0.1, batch_size = 256, verbose=2, epochs=5)
#evaluate on unseen data
score = model.evaluate(x_test, y_test, verbose=0)
print('Test accuarcy: {:0.2f}%'.format(score[1] * 100))
训练结果如下图所示:
测试准确率达到了 92.20% 的 top 5 准确率。
准备 WEB 格式的模型
在我们得到满意的模型准确率后,我们将模型保存下来,以便进行下一步的转换。
model.save('keras.h5')
为转换安装 tensorflow.js:
!pip install tensorflowjs
接着我们对模型进行转换:
!mkdir model
!tensorflowjs_converter --input_format keras keras.h5 model/
这个步骤将创建一些权重文件和包含模型架构的 json 文件。
通过 zip 将模型进行压缩,以便将其下载到本地机器上:
!zip -r model.zip model
最后下载模型:
from google.colab import files
files.download('model.zip')
在浏览器上进行推断
本节中,我们将展示如何加载模型并且进行推断。假设我们有一个尺寸为 300*300 的画布。在这里,我们不会详细介绍函数接口,而是将重点放在 TensorFlow.js 的部分。
加载模型
为了使用 TensorFlow.js,我们首先使用下面的脚本:
你的本地机器上需要有一台运行中的服务器来托管权重文件。你可以在 GitHub 上创建一个 apache 服务器或者托管网页,就像我在我的项目中所做的那样(https://github/zaidalyafeai/zaidalyafeai.github.io/tree/master/sketcher)。
接着,通过下面的代码将模型加载到浏览器:
model = await tf.loadModel('model/model.json')
关键字 await 的意思是等待模型被浏览器加载。
预处理
在进行预测前,我们需要对数据进行预处理。首先从画布中获取图像数据:
//the minimum boudning box around the current drawing
const mbb = getMinBox()
//cacluate the dpi of the current window
const dpi = window.devicePixelRatio
//extract the image data
const imgData = canvas.contextContainer.getImageData(mbb.min.x * dpi, mbb.min.y * dpi,
(mbb.max.x - mbb.min.x) * dpi, (mbb.max.y - mbb.min.y) * dpi);
文章稍后将介绍 getMinBox()。dpi 变量被用于根据屏幕像素的密度对裁剪出的画布进行拉伸。
我们将画布当前的图像数据转化为一个张量,调整大小并进行归一化处理:
function preprocess(imgData)
{
return tf.tidy(()=>{
//convert the image data to a tensor
let tensor = tf.fromPixels(imgData, numChannels= 1)
//resize to 28 x 28
const resized = tf.image.resizeBilinear(tensor, [28, 28]).toFloat()
// Normalize the image
const offset = tf.scalar(255.0);
const normalized = tf.scalar(1.0).sub(resized.p(offset));
//We add a dimension to get a batch shape
const batched = normalized.expandDims(0)
return batched
})
}
我们使用 model.predict 进行预测,这将返回一个规模为「N, 100」的概率。
const pred = model.predict(preprocess(imgData)).dataSync()
我们可以使用简单的函数找到 top 5 概率。
提升准确率
请记住,我们的模型接受的输入数据是规模为 [N, 28, 28, 1] 的张量。我们绘图画布的尺寸为 300*300,这可能是两个手绘图像的大小,或者用户可以在上面绘制一个小图像。最好只裁剪包含当前手绘图像的方框。为了做到这一点,我们通过找到左上方和右下方的点来提取围绕图像的最小边界框。
//record the current drawing coordinates
function recordCoor(event)
{
//get current mouse coordinate
var pointer = canvas.getPointer(event.e);
var posX = pointer.x;
var posY = pointer.y;
//record the point if withing the canvas and the mouse is pressed
if(posX >=0 && posY >= 0 && mousePressed)
{
coords.push(pointer)
}
}
//get the best bounding box by finding the top left and bottom right cornders
function getMinBox(){
var coorX = coords.map(function(p) {return p.x});
var coorY = coords.map(function(p) {return p.y});
//find top left corner
var min_coords = {
x : Math.min.apply(null, coorX),
y : Math.min.apply(null, coorY)
}
//find right bottom corner
var max_coords = {
x : Math.max.apply(null, coorX),
y : Math.max.apply(null, coorY)
}
return {
min : min_coords,
max : max_coords
}
}
用手绘图像进行测试
下图显示了一些第一次绘制的图像以及准确率最高的类别。所有的手绘图像都是我用鼠标画的,用笔绘制的话应该会得到更高的准确率。
原文链接:https://medium/tensorflow/train-on-google-colab-and-run-on-the-browser-a-case-study-8a45f9b1474e
- ?
手把手教你如何用TensorFlow实现基于DNN的文本分类
Grace
展开
雷锋网按:本文源自一位数据科学开发者的个人博客,雷锋网编译。
许多开发者向新手建议:如果你想要入门机器学习,就必须先了解一些关键算法的工作原理,然后再开始动手实践。但我不这么认为。
我觉得实践高于理论,新手首先要做的是了解整个模型的工作流程,数据大致是怎样流动的,经过了哪些关键的结点,最后的结果在哪里获取,并立即开始动手实践,构建自己的机器学习模型。至于算法和函数内部的实现机制,可以等了解整个流程之后,在实践中进行更深入的学习和掌握。
那么问题来了,既然作为初学者不需要掌握算法细节,但实现模型的过程中又必须用到相关算法,怎么办呢?答案是借助于互联网上已经实现好的函数库,例如 TensorFlow。
在本文中,我们将利用 TensorFlow 实现一个基于深度神经网络(DNN)的文本分类模型,希望对各位初学者有所帮助。文中所涉完整代码已经在 GitHub 上开源,感兴趣的朋友可以在以下链接中下载:
http://t/RXiP3Om
下面是正式的教程内容:
关于 TensorFlow
TensorFlow 是谷歌旗下一个开源的机器学习框架。从它的名字就能看出这个框架基本的工作原理:由多维数组构成的张量(tensor)在图(graph)结点之间定向流动(flow),从输入走到输出。
在 TensorFlow 中,每次运算都可以用数据流图(dataflow graph)的方式表示。每个数据流图都有以下两个重要元素:
● 一组 tf.Operation 对象,代表运算本身;
● 一组 tf.Tensor 对象,代表被运算的数据。
如下图所示,这里我们以一个简单的例子说明什么计算流图具体是怎样运行的。
假设图中的 x=[1,3,6],y=[1,1,1]。由于 tf.Tensor 被用来表示运算数据,因此在 TensorFlow 中我们会首先定义两个 tf.Tensor 常量对象存放数据。然后再用 tf.Operation 对象定义图中的加法运算,具体代码如下:
import tensorflow as tf
x = tf.constant([1,3,6])
y = tf.constant([1,1,1])
op = tf.add(x,y)
现在,我们已经定义了数据流图的两个重要元素:tf.Operation 和 tf.Tensor,那么如何构建图本身呢,具体代码如下:
my_graph = tf.Graph()
with my_graph.as_default():
x = tf.constant([1,3,6])
y = tf.constant([1,1,1])
op = tf.add(x,y)
至此我们已经完成了数据流图的定义,在 TensorFlow 中,只有先定义了图,才能进行后续的计算操作(即驱动数据在图的结点间定向流动)。这里 TensorFlow 又规定,要进行后续的计算,必须通过 tf.Session 来统一管理,因此我们还要定义一个 tf.Session 对象,即会话。
在 TensorFlow 中,tf.Session 专门用来封装 tf.Operation 在 tf.Tensor 基础上执行的操作环境。因此,在定义 tf.Session 对象时,也需要传入相应的数据流图(可以通过 graph 参数传入),本例中具体的代码如下:
with tf.Session(graph=my_graph) as sess:
定义好 tf.Session 之后,我们可以通过 tf.Session.run() 方法来执行对应的数据流图。run() 方法可以通过 fetches 参数传入相应 tf.Operation 对象,并导入与 tf.Operation 相关的所有 tf.Tensor 对象,然后递归执行与当前 tf.Operation 有依赖关系的所有操作。本例中具体执行的是求和操作,实现代码如下:
with tf.Session(graph=my_graph) as sess:
result = sess.run(fetches=op)
print(result)
>>> [2 4 7]
可以看到运算结果是 [2 4 7]。
关于预测模型
了解 TensorFlow 的基本原理之后,下面的任务是如何构建一个预测模型。简单来说,机器学习算法 + 数据就等于预测模型。构建预测模型的流程如下图所示:
如图,经过数据训练的机器学习算法就是模型。训练好一个模型之后,输入待预测数据,就能得到相应的预测结果。大体流程如下图所示:
在本例中,我们将要构建的模型需要根据输入文本,输出相应的类别,即完成文本分类的工作。因此这里的输入应该是文本(text),输出是类别(category)。更具体地说,本例中我们已经事先获取了标记数据(即一些已经标明了类别的文本段),然后用这些数据对算法进行训练,最后再用训练好的模型对新文本分类。这一过程也就是通常所说的监督学习(supervised learning)。另外,由于我们的任务是对文本数据进行分类,所以也属于分类问题的范畴。
为了构建该文本分类模型,下面我们需要介绍一些神经网络的基础知识。
关于神经网络
从本质上说,神经网络是计算模型(computational model)的一种。(注:这里所谓计算模型是指通过数学语言和数学概念描述系统的方法)并且这种计算模型还能够自动完成学习和训练,不需要精确编程。
最原始也是最基础的一个神经网络算法模型是感知机模型(Perceptron),关于感知机模型的详细介绍请参见这篇博客:
http://t/R5MphRp
由于神经网络模型是模拟人类大脑神经系统的组织结构而提出的,因此它与人类的脑神经网络具有相似的结构。
如上图所示,一般的神经网络结构可以分为三层:输入层、隐蔽层(hidden layer)和输出层。
为了深入理解神经网络究竟是如何工作的,我们需要利用 TensorFlow 自己亲手构建一个神经网络模型,下面介绍一个具体的实例。(本例部分内容源自 GitHub 上的一段开源代码:)链接
本例中,我们有两个隐蔽层(关于隐蔽层层数的选择是另一个问题,更详细的内容可以参考:)。概括地说,隐蔽层的主要作用是将输入层的数据转换成一种输出层更便于利用的形式。链接
如图所示,本例中输入层的每个结点都代表了输入文本中的一个词,接下来是第一个隐蔽层。这里需要注意的是,第一层隐蔽层的结点个数选择也是一项重要的任务,通常被称为特征选择。
图中的每个结点(也被称为神经元),都会搭配一个权重。而我们下面所谓训练过程其实就是不断调整这些权重值,让模型的实际输出和预想输出更匹配的过程。当然,除了权重之外,整个网络还要加上一个偏差值。(关于偏差的详细介绍详见:)链接
对每个结点做加权和并加上一个偏差值之后,还需要经过激活函数(activation function)的处理才能输出到下一层 。实际上,这里激活函数确定了每个结点的最终输出情况,同时为整个模型加入了非线性元素。如果用台灯来做比喻的话,激活函数的作用就相当于开关。实际研究中根据应用的具体场景和特点,有各种不同的激活函数可供选择,这里屏蔽层选择的是 ReLu 函数。
另外图中还显示了第二个隐蔽层,它的功能和第一层并没有本质区别,唯一的不同就是它的输入是第一层的输出,而第一层的输入则是原始数据。
最后是输出层,本例中应用了独热编码的方式来对结果进行分类。这里所谓独热编码是指每个向量中只有一个元素是 1,其他均为 0 的编码方式。例如我们要将文本数据分为三个类别(体育、航空和电脑绘图),则编码结果为:
这里独热编码的好处是:输出结点的个数恰好等于输出类别的个数。此外,输出层和前面的隐蔽层结构类似,我们也要为每个结点搭配一个权重值,加上恰当的偏差,最后通过激活函数的处理。
但本例中输出层的激活函数与隐蔽层的激活函数不同。由于本例的最终目的是输出每个文本对应的类别信息,而这里所有类别之间又是互斥的关系。基于这些特点,我们在输出层选择了 Softmax 函数作为激活函数。该函数的特点是可以将输出值转换为 0-1 之间的一个小数值,并且这些小数值的和为 1。于是正好可以用这些小数表示每个类别的可能性分布情况。假如刚才提到的三个类别原本的输出值为 1.2、0.9 和 0.4,则通过 Softmax 函数的处理后,得到的结果为:
可以看到这三个小数的和正好为 1。
到目前为止,我们已经明确了该神经网络的数据流图,下面为具体的代码实现:
# Network Parameters
n_hidden_1 = 10 # 1st layer number of features
n_hidden_2 = 5 # 2nd layer number of features
n_input = total_words # Words in vocab
n_classes = 3 # Categories: graphics, space and baseball
def multilayer_perceptron(input_tensor, weights, biases):
layer_1_multiplication= tf.matmul(input_tensor, weights['h1'])
layer_1_addition= tf.add(layer_1_multiplication, biases['b1'])
layer_1_activation= tf.nn.relu(layer_1_addition)
# Hidden layer with RELU activation
layer_2_multiplication= tf.matmul(layer_1_activation, weights['h2'])
layer_2_addition= tf.add(layer_2_multiplication, biases['b2'])
layer_2_activation= tf.nn.relu(layer_2_addition)
# Output layer with linear activation
out_layer_multiplication= tf.matmul(layer_2_activation, weights['out'])
out_layer_addition= out_layer_multiplication + biases['out']
return out_layer_addition
神经网络的训练
如前所述,模型训练中一项非常重要的任务就是调整结点的权重。本节我们将介绍如何在 TensorFlow 中实现这一过程。
在 TensorFlow 中,结点权重和偏差值以变量的形式存储,即 tf.Variable 对象。在数据流图调用 run() 函数的时候,这些值将保持不变。在一般的机器学习场景中,权重值和偏差值的初始取值都通过正太分布确定。具体代码如下图所示:
weights = {
'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}
biases = {
'b1': tf.Variable(tf.random_normal([n_hidden_1])),
'b2': tf.Variable(tf.random_normal([n_hidden_2])),
'out': tf.Variable(tf.random_normal([n_classes]))
以初始值运行神经网络之后,会得到一个实际输出值 z,而我们的期望输出值是 expected,这时我们需要做的就是计算两者之间的误差,并通过调整权重等参数使之最小化。一般计算误差的方法有很多,这里因为我们处理的是分类问题,因此采用交叉熵误差。(关于为什么分类问题选用交叉熵,参见:)连接
在 TensorFlow 中,我们可以通过调用 tf.nn.softmax_cross_entropy_with_logits() 函数来计算交叉熵误差,因为这里我们的激活函数选择了 Softmax ,因此误差函数中出现了 softmax_ 前缀。具体代码如下(代码中我们同时调用了 tf.reduced_mean() 函数来计算平均误差):
# Construct model
prediction = multilayer_perceptron(input_tensor, weights, biases)
# Define loss
entropy_loss = tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=output_tensor)
loss = tf.reduce_mean(entropy_loss)
得到误差之后,下面的任务是如何使之最小化。这里我们选择的方法是最常用的随机梯度下降法,其直观的原理图如下所示:
同样,用来计算梯度下降的方法也有很多,这里我们采用了 Adaptive Moment Estimation (Adam) 优化法,即自适应矩估计的优化方法,具体在 TensorFlow 中的体现是 tf.train.AdamOptimizer(learning_rate).minimize(loss) 函数。这里我们需要传入 learning_rate 参数以决定计算梯度时的步进长度。
非常方便的一点是,AdamOptimizer() 函数封装了两种功能:一是计算梯度,二是更新梯度。换句话说,调用该函数不但能计算梯度值,还能将计算结果更新到所有 tf.Variables 对象中,这一点大大降低了编程复杂度。
具体模型训练部分的代码如下所示:
learning_rate = 0.001
entropy_loss = tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=output_tensor)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
数据处理
本例中,我们得到的原始数据是许多英文的文本片段,为了将这些数据导入模型中,我们需要对原始数据进行必要的预处理过程。这里具体包括两个部分:
● 为每个单词编码;
● 为每个文本片段创建对应的张量表示,其中以数字 1 代表出现了某个单词,0 表示没有该单词。
具体实现代码如下:
import numpy as np #numpy is a package for scientific computing
from collections import Counter
vocab = Counter()
text = "Hi from Brazil"
#Get all words
for word in text.split(' '):
vocab[word]+=1
#Convert words to indexes
def get_word_2_index(vocab):
word2index = {}
for i,word in enumerate(vocab):
word2index[word] = i
return word2index
#Now we have an index
word2index = get_word_2_index(vocab)
total_words = len(vocab)
#This is how we create a numpy array (our matrix)
matrix = np.zeros((total_words),dtype=float)
#Now we fill the values
for word in text.split():
matrix[word2index[word]] += 1
print(matrix)
>>> [ 1. 1. 1.]
从以上代码可以看到,当输入文本是“Hi from Brazil”时,输出矩阵是 [ 1. 1. 1.]。而当输入文本只有“Hi”时又会怎么样呢,具体代码和结果如下:
text = "Hi"
matrix[word2index[word.lower()]] += 1
>>> [ 1. 0. 0.]
可以看到,这时的输出是 [ 1. 0. 0.]。
相应的,我们也可以对类别信息进行编码,只不过这时使用的是独热编码:
y = np.zeros((3),dtype=float)
if category == 0:
y[0] = 1.# [ 1. 0. 0.]
elif category == 1:
y[1] = 1.# [ 0. 1. 0.]
else:
y[2] = 1.# [ 0. 0. 1.]
运行模型并预测
至此我们已经对 TensorFlow、神经网络模型、模型训练和数据预处理等方面有了初步的了解,下面我们将演示如何将这些知识应用于实际的数据。
这里我们的数据来源是 20 Newsgroups,其中包括了 18000 篇新闻稿,覆盖率 20 个类别,开源免费,下载地址为:
http...
- ?
Tensorflow的工作原理以及如何使用它
Milo
展开
Tensorflow 发布已经有三年,如今它已成为深度学习生态系统的基石。然而对于初学者来说它并不怎么简单易懂,与 PyTorch 或 DyNet 这样的运行即定义的神经网络库相比就更明显了。
有很多 Tensorflow 的入门教程,内容涵盖线性回归、MNIST 分类乃至机器翻译。这些内容具体、实用的指南能帮助人们快速启动并运行 Tensorflow 项目,并且可以作为类似项目的切入点。但有的开发者开发的应用并没有很好的教程参考,还有的项目在探索全新的路线(研究中很常见),对于这些开发者来说入门 Tensorflow 是非常容易感到困惑的。
我写这篇文章就想弥补这一缺口。本文不会研究某个具体任务,而是提出更加通用的方法,并解析 Tensorflow 的基础抽象概念。掌握好这些概念后,用 Tensorflow 进行深度学习就会更加直观易懂。
目标受众
本教程适用于在编程和机器学习方面有一定经验,并想要入门 Tensorflow 的从业者。他们可以是:想在深度学习课程的最后一个项目中使用 Tensorflow 的 CS 专业学生;刚刚被调到涉及深度学习的项目的软件工程师;或者是一位处于困惑之中的 Google AI 新手(向 Jacob 大声打个招呼吧)。如果你需要基础知识入门,请参阅以下资源。这些都了解的话,我们就开始吧!
理解 Tensorflow
Tensorflow 不是一个普通的 Python 库。
大多数 Python 库被编写为 Python 的自然扩展形式。当你导入一个库时,你得到的是一组变量、函数和类,它们补充并扩展了你的代码“工具箱”。使用这些库时,你知道它们将产生怎样的结果。我认为谈及 Tensorflow 时应该抛弃这些认识,这些认知从根本上就不符合 Tensorflow 的理念,无法反映 TF 与其它代码交互的方式。
Python 和 Tensorflow 之间的联系,可以类比 Javascript 和 HTML 之间的关系。Javascript 是一种全功能的编程语言,可以实现各种出色的效果。HTML 是用于表示某种类型的实用计算抽象(这里指的是可由 Web 浏览器呈现的内容)的框架。Javascript 在交互式网页中的作用是组装浏览器看到的 HTML 对象,然后在需要时通过将其更新为新的 HTML 来与其交互。
与 HTML 类似,Tensorflow 是用于表示某种类型的计算抽象(称为“计算图”)的框架。当我们用 Python 操作 Tensorflow 时,我们用 Python 代码做的第一件事是组装计算图。之后我们的第二个任务就是与它进行交互(使用 Tensorflow 的“会话”)。但重要的是,要记住计算图不在变量内部,它处在全局命名空间内。莎士比亚曾经说过:“所有的 RAM 都是一个阶段,所有的变量都只不过是指针。”
第一个关键抽象:计算图
我们在浏览 Tensorflow 文档时,有时会发现内容提到“图形”和“节点”。如果你仔细阅读、深入挖掘,甚至可能已经发现了这个页面,该页面中涵盖的内容我将以更精确和技术化的风格详细解释。本节将从顶层入手,把握关键的直觉概念,同时略过一些技术细节。
那么什么是计算图?它实质上是一个全局数据结构:计算图是一个有向图,捕获有关计算方法的指令。
我们来看看如何构建一个示例。下图中,上半部分是我们运行的代码和它的输出,下半部分是结果计算图。
显然,仅仅导入 Tensorflow 并不会给我们生成一个有趣的计算图,而只有一个孤独的,空白的全局变量。但是当我们调用一个 Tensorflow 操作时会发生什么呢?
快看!我们得到了一个节点,它包含常量:2。我知道你很惊讶,惊讶的是一个名为 tf.constant 的函数。当我们打印这个变量时,我们看到它返回一个 tf.Tensor 对象,它是一个指向我们刚创建的节点的指针。为了强调这一点,这里是另一个例子:
每次我们调用 tf.constant 的时候,我们都会在图中创建一个新节点。即使节点在功能上与现有节点完全相同,即使我们将节点重新分配给同一个变量,甚至我们根本没有将其分配给变量,结果都一样。
相反,如果创建一个新变量并将其设置为与现有节点相等,则只需将该指针复制到该节点,并且不会向该图添加任何内容:
好的,我们更进一步。
现在我们来看——这才是我们要的真正的计算图表!请注意,+ 操作在 Tensorflow 中过载,所以同时添加两个张量会在图中增加一个节点,尽管它看起来不像是 Tensorflow 操作。
好的,所以 two_node 指向包含 2 的节点,three_node 指向包含 3 的节点,而 sum_node 指向包含... + 的节点?什么情况?它不是应该包含 5 吗?
事实证明,没有。计算图只包含计算步骤,不包含结果。至少...... 还没有!
第二个关键抽象:会话
如果错误地理解 TensorFlow 抽象也有个疯狂三月竞赛(美国大学篮球繁忙冠军赛季),那么“会话”将成为每年排名第一的种子选手。能获此尴尬的荣誉,是因为会话的命名反直觉,应用却如此广泛——几乎每个 Tensorflow 程序都至少会调用一次 tf.Session () 。
会话的作用是处理内存分配和优化,使我们能够实际执行由图形指定的计算。可以将计算图想象为我们想要执行的计算的“模板”:它列出了所有的步骤。为了使用这个图表,我们还需要发起一个会话,它使我们能够实际地完成任务。例如,遍历模板的所有节点来分配一组用于存储计算输出的存储器。为了使用 Tensorflow 进行各种计算,我们既需要图也需要会话。
会话包含一个指向全局图的指针,该指针通过指向所有节点的指针不断更新。这意味着在创建节点之前还是之后创建会话都无所谓。
创建会话对象后,可以使用 sess.run (node) 返回节点的值,并且 Tensorflow 将执行确定该值所需的所有计算。
精彩!我们还可以传递一个列表,sess.run ([node1,node2,...]),并让它返回多个输出:
一般来说,sess.run () 调用往往是最大的 TensorFlow 瓶颈之一,所以调用它的次数越少越好。可以的话在一个 sess.run () 调用中返回多个项目,而不是进行多个调用。
占位符和 feed_dict
我们迄今为止所做的计算一直很乏味:没有机会获得输入,所以它们总是输出相同的东西。一个实用的应用可能涉及构建这样一个计算图:它接受输入,以某种(一致)方式处理它,并返回一个输出。
最直接的方法是使用占位符。占位符是一种用于接受外部输入的节点。
……这是个糟糕的例子,因为它引发了一个异常。占位符预计会被赋予一个值,但我们没有提供,因此 Tensorflow 崩溃了。
为了提供一个值,我们使用 sess.run () 的 feed_dict 属性。
好多了。注意传递给 feed_dict 的数值格式。这些键应该是与图中占位符节点相对应的变量(如前所述,它实际上意味着指向图中占位符节点的指针)。相应的值是要分配给每个占位符的数据元素——通常是标量或 Numpy 数组。第三个关键抽象:计算路径下面是另一个使用占位符的例子:
为什么第二次调用 sess.run () 会失败?我们并没有在检查 input_placeholder,为什么会引发与 input_placeholder 相关的错误?答案在于最终的关键 Tensorflow 抽象:计算路径。还好这个抽象非常直观。
当我们在依赖于图中其他节点的节点上调用 sess.run () 时,我们也需要计算这些节点的值。如果这些节点有依赖关系,那么我们需要计算这些值(依此类推......),直到达到计算图的“顶端”,也就是所有的节点都没有前置节点的情况。
考察 sum_node 的计算路径:
所有三个节点都需要评估以计算 sum_node 的值。最重要的是,这里面包含了我们未填充的占位符,并解释了例外情况!
相反,考察 three_node 的计算路径:
根据图的结构,我们不需要计算所有的节点也可以评估我们想要的节点!因为我们不需要评估 placeholder_node 来评估 three_node,所以运行 sess.run (three_node) 不会引发异常。
Tensorflow 仅通过必需的节点自动路由计算这一事实是它的巨大优势。如果计算图非常大并且有许多不必要的节点,它就能节约大量运行时间。它允许我们构建大型的“多用途”图形,这些图形使用单个共享的核心节点集合根据采取的计算路径来做不同的任务。对于几乎所有应用程序而言,根据所采用的计算路径考虑 sess.run () 的调用方法是很重要的。
变量和副作用
到目前为止,我们已经看到两种类型的“无祖先”节点:tf.constant(每次运行都一样)和 tf.placeholder(每次运行都不一样)。还有第三种节点:通常情况下具有相同的值,但也可以更新成新值。这个时候就要用到变量。
了解变量对于使用 Tensorflow 进行深度学习来说至关重要,因为模型的参数就是变量。在训练期间,你希望通过梯度下降在每个步骤更新参数,但在计算过程中,你希望保持参数不变,并将大量不同的测试输入集传入到模型中。模型所有的可训练参数很有可能都是变量。
要创建变量,请使用 tf.get_variable ()。tf.get_variable () 的前两个参数是必需的,其余是可选的。它们是 tf.get_variable (name,shape)。name 是一个唯一标识这个变量对象的字符串。它在全局图中必须是唯一的,所以要确保不会出现重复的名称。shape 是一个与张量形状相对应的整数数组,它的语法很直观——每个维度对应一个整数,并按照排列。例如,一个 3×8 的矩阵可能具有形状 [3,8]。要创建标量,请使用空列表作为形状:[]。
发现另一个异常。一个变量节点在首次创建时,它的值基本上就是“null”,任何尝试对它进行计算的操作都会抛出这个异常。我们只能先给一个变量赋值后才能用它做计算。有两种主要方法可以用于给变量赋值:初始化器和 tf.assign ()。我们先看看 tf.assign ():
与我们迄今为止看到的节点相比,tf.assign (target,value) 有一些独特的属性:
标识操作。tf.assign (target,value) 不做任何计算,它总是与 value 相等。
副作用。当计算“流经”assign_node 时,就会给图中的其他节点带来副作用。在这种情况下,副作用就是用保存在 zero_node 中的值替换 count_variable 的值。
非依赖边。即使 count_variable 节点和 assign_node 在图中是相连的,两者都不依赖于其他节点。这意味着在计算任一节点时,计算不会通过该边回流。不过,assign_node 依赖 zero_node,它需要知道要分配什么。
“副作用”节点充斥在大部分 Tensorflow 深度学习工作流中,因此,请确保你对它们了解得一清二楚。当我们调用 sess.run (assign_node) 时,计算路径将经过 assign_node 和 zero_node。
当计算流经图中的任何节点时,它还会让该节点控制的副作用(绿色所示)起效。由于 tf.assign 的特殊副作用,与 count_variable(之前为“null”)关联的内存现在被永久设置为 0。这意味着,当我们下一次调用 sess.run (count_variable) 时,不会抛出任何异常。相反,我们将得到 0。
接下来,让我们来看看初始化器:
这里都发生了什么?为什么初始化器不起作用?
问题在于会话和图之间的分隔。我们已经将 get_variable 的 initializer 属性指向 const_init_node,但它只是在图中的节点之间添加了一个新的连接。我们还没有做任何与导致异常有关的事情:与变量节点(保存在会话中,而不是图中)相关联的内存仍然为“null”。我们需要通过会话让 const_init_node 更新变量。
为此,我们添加了另一个特殊节点:init = tf.global_variables_initializer ()。与 tf.assign () 类似,这是一个带有副作用的节点。与 tf.assign () 不一样的是,我们实际上并不需要指定它的输入!tf.global_variables_initializer () 将在其创建时查看全局图,自动将依赖关系添加到图中的每个 tf.initializer 上。当我们调用 sess.run (init) 时,它会告诉每个初始化器完成它们的任务,初始化变量,这样在调用 sess.run (count_variable) 时就不会出错。
变量共享
你可能会碰到带有变量共享的 Tensorflow 代码,代码有它们的作用域,并设置“reuse=True”。我强烈建议你不要在代码中使用变量共享。如果你想在多个地方使用单个变量,只需要使用指向该变量节点的指针,并在需要时使用它。换句话说,对于打算保存在内存中的每个参数,应该只调用一次 tf.get_variable ()。
优化器
最后:进行真正的深度学习!如果你还在状态,那么其余的概念对于你来说应该是非常简单的。
在深度学习中,典型的“内循环”训练如下:
获取输入和 true_output
根据输入和参数计算出一个“猜测”
根据猜测和 true_output 之间的差异计算出一个“损失”
根据损失的梯度更新参数
让我们把所有东西放在一个脚本里,解决一个简单的线性回归问题:
正如你所看到的,损失基本上没有变化,而且我们对真实参数有了很好的估计。这部分代码只有一两行对你来说是新的:
既然你对 Tensorflow 的基本概念已经有了很好的理解,这段代码应该很容易解释!第一行,optimizer = tf.train.GradientDescentOptimizer (1e-3) 不会向图中添加节点。它只是创建了一个 Python 对象,包含了一些有用的函数。第二行 train_op = optimizer.minimize (loss),将一个节点添加到图中,并将一个指针赋给 train_op。train_op 节点没有输出,但有一个非常复杂的副作用:
train_op 回溯其输入的计算路径,寻找变量节点。对于找到的每个变量节点,它计算与损失相关的变量梯度。然后,它为该变量计算新值:当前值减去梯度乘以学习率。最后,它æ‰...
- ?
深度学习入门篇——手把手教你用 TensorFlow 训练模型
虞若风
展开
更多腾讯海量技术文章,请关注腾讯云技术社区:https://cloud.tencent/community
作者:付越
导语
Tensorflow在更新1.0版本之后多了很多新功能,其中放出了很多用tf框架写的深度网络结构(https://github/tensorflow/models ),大大降低了开发难度,利用现成的网络结构,无论fine-tuning还是重新训练方便了不少。最近笔者终于跑通TensorFlow Object Detection API的ssd_mobilenet_v1模型,这里记录下如何完整跑通数据准备到模型使用的整个过程,相信对自己和一些同学能有所帮助。
Object Detection API提供了5种网络结构的预训练的权重,全部是用COCO数据集进行训练,这五种模型分别是SSD+mobilenet、SSD+inception_v2、R-FCN+resnet101、faster RCNN+resnet101、faster RCNN+inception+resnet101。各个模型的精度和计算所需时间如下。下面及介绍下如何使用Object Detection去训练自己的模型。
这里TensorFlow的安装就不再说明了,网上的教程一大把,大家可以找到很详尽的安装TensorFlow的文档。
训练前准备:
使用protobuf来配置模型和训练参数,所以API正常使用必须先编译protobuf库,这里可以下载直接编译好的pb库(https://github/google/protobuf/releases ),解压压缩包后,把protoc加入到环境变量中:
$ cd tensorflow/models$ protoc object_detection/protos/*.proto --python_out=.
(我是把protoc加到环境变量中,遇到找不到*.proto文件的报错,后来把protoc.exe放到models/object_detection目录下,重新执行才可以)
然后将models和slim(tf高级框架)加入python环境变量:
PYTHONPATH=$PYTHONPATH:/your/path/to/tensorflow/models:/your/path/to/tensorflow/models/slim
数据准备:
数据集需要转化成PASCAL VOC结构,API提供了create_pascal_tf_record.py,把VOC结构数据集转换成.record格式。不过我们发现更简单的方式,Datitran提供一种更简单生产.record格式的方法。
首先需要先要标注图像相应标签,这里可以使用labelImg工具。每标注一张样本,即生成一个xml的标注文件。然后,把这些标注的xml文件,按训练集与验证集分别放置到两个目录下,在Datitran提供了xml_to_csv.py脚本。这里只要指定标注的目录名即可。接下来,然后需要我们把对应的csv格式转换成.record格式。
def main(): # image_path = os.path.join(os.getcwd(), 'annotations') image_path = r'D:\training-sets\object-detection\sunglasses\label\test' xml_df = xml_to_csv(image_path) xml_df.to_csv('sunglasses_test_labels.csv', index=None) print('Successfully converted xml to csv.')
调用generate_tfrecord.py,注意要指定--csv_input与--output_path这两个参数。执行下面命令:
python generate_tfrecord.py --csv_input=sunglasses_test_labels.csv --output_path=sunglass_test.record
这样就生成了训练及验证用的train.record与test.record。接下来指定标签名称,仿照models/ object_detection/data/ pet_label_map.pbtxt,重新创建一个文件,指定标签名。
item { id: 1 name: 'sunglasses'}
训练:
根据自己的需要,选择一款用coco数据集预训练的模型,把前缀model.ckpt放置在待训练的目录,这里meta文件保存了graph和metadata,ckpt保存了网络的weights,这几个文件表示预训练模型的初始状态。
打开ssd_mobilenet_v1_pets.config文件,并做如下修改:
num_classes:修改为自己的classes num
将所有PATH_TO_BE_CONFIGURED的地方修改为自己之前设置的路径(共5处)
其他参数均保持默认参数。
准备好上述文件后就可以直接调用train文件进行训练。
python object_detection/train.py \--logtostderr \--pipeline_config_path= D:/training-sets /data-translate/training/ssd_mobilenet_v1_pets.config \--train_dir=D:/training-sets/data-translate/training
TensorBoard监控:
通过tensorboard工具,可以监控训练过程,输入西面指令后,在浏览器输入localhost:6006(默认)即可。
tensorboard --logdir= D:/training-sets/data-translate/training
这里面有很多指标曲线,甚至有模型网络架构,笔者对于这里面很多指标含义还没有弄明白,不过感觉出TensorBoard这个工具应该是极其强大。不过我们可以通过Total_Loss来看整体训练的情况。
从整体上看,loss曲线确实是收敛的,整体的训练效果还是满意的。另外,TensorFlow还提供了训练过程中利用验证集验证准确性的能力,但是笔者在调用时,仍有些问题,这里暂时就不详细说明了。
Freeze Model模型导出:
查看模型实际的效果前,我们需要把训练的过程文件导出,生产.pb的模型文件。本来,tensorflow/python/tools/freeze_graph.py提供了freeze model的api,但是需要提供输出的final node names(一般是softmax之类的最后一层的激活函数命名),而object detection api提供提供了预训练好的网络,final node name并不好找,所以object_detection目录下还提供了export_inference_graph.py。
python export_inference_graph.py \--input_type image_tensor--pipeline_config_path D:/training-sets /data-translate/training/ssd_mobilenet_v1_pets.config \--trained_checkpoint_prefix D:/training-sets /data-translate/training/ssd_mobilenet_v1_pets.config /model.ckpt-* \--output_directory D:/training-sets /data-translate/training/result
导出完成后,在output_directory下,会生成frozen_inference_graph.pb、model.ckpt.data-00000-of-00001、model.ckpt.meta、model.ckpt.data文件。
调用生成模型:
目录下本身有一个调用的例子,稍微改造如下:
import cv2import numpy as npimport tensorflow as tffrom object_detection.utils import label_map_utilfrom object_detection.utils import visualization_utils as vis_utilclass TOD(object): def __init__(self): self.PATH_TO_CKPT = r'D:\lib\tf-model\models-master\object_detection\training\frozen_inference_graph.pb' self.PATH_TO_LABELS = r'D:\lib\tf-model\models-master\object_detection\training\sunglasses_label_map.pbtxt' self.NUM_CLASSES = 1 self.detection_graph = self._load_model() self.category_index = self._load_label_map() def _load_model(self): detection_graph = tf.Graph() with detection_graph.as_default(): od_graph_def = tf.GraphDef() with tf.gfile.GFile(self.PATH_TO_CKPT, 'rb') as fid: serialized_graph = fid.read() od_graph_def.ParseFromString(serialized_graph) tf.import_graph_def(od_graph_def, name='') return detection_graph def _load_label_map(self): label_map = label_map_util.load_labelmap(self.PATH_TO_LABELS) categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=self.NUM_CLASSES, use_display_name=True) category_index = label_map_util.create_category_index(categories) return category_index def detect(self, image): with self.detection_graph.as_default(): with tf.Session(graph=self.detection_graph) as sess: # Expand dimensions since the model expects images to have shape: [1, None, None, 3] image_np_expanded = np.expand_dims(image, axis=0) image_tensor = self.detection_graph.get_tensor_by_name('image_tensor:0') boxes = self.detection_graph.get_tensor_by_name('detection_boxes:0') scores = self.detection_graph.get_tensor_by_name('detection_scores:0') classes = self.detection_graph.get_tensor_by_name('detection_classes:0') num_detections = self.detection_graph.get_tensor_by_name('num_detections:0') # Actual detection. (boxes, scores, classes, num_detections) = sess.run( [boxes, scores, classes, num_detections], feed_dict={image_tensor: image_np_expanded}) # Visualization of the results of a detection. vis_util.visualize_boxes_and_labels_on_image_array( image, np.squeeze(boxes), np.squeeze(classes).astype(np.int32), np.squeeze(scores), self.category_index, use_normalized_coordinates=True, line_thickness=8) cv2.namedWindow("detection", cv2.WINDOW_NORMAL) cv2.imshow("detection", image) cv2.waitKey(0)if __name__ == '__main__': image = cv2.imread('image.jpg') detecotr = TOD() detecotr.detect(image)
下面是一些图片的识别效果:
- ?
【TensorFlow超级指南】你能想到的TF教程和资源都在这里了
妙彤
展开
新智元报道
来源:bytegain
编译:三石
【新智元导读】众所周知,TensorFlow已然成为机器学习的热门工具。不论是学习还是从事与机器学习相关的工作,能够灵活使用TensorFlow可以大幅提高作业效率。本文涵盖与TensorFlow相关的教程、书籍、工具、求职等的大量信息。尽数资源,应有尽有。
不论你是刚刚“入坑”机器学习,亦或是在机器学习领域摸爬滚打多年,本文所总结的TensorFlow资源,总有一款是你需要的!
话不多说,上干货!
教程
Martin Grner课程—《无需成为博士即可学会TensorFlow和机器学习》:
浏览器版本过低,暂不支持视频播放如果你已经掌握了线性代数,那么这是一个很好的起点。 因为它会涉及几个高级概念,例如:
什么是神经元;不同类型的激活函数以及为何要使用Relu;如何通过dropout提高模型的精确度;如何评估模型以及如何调参。
Jacob Buckman—《TensorFlow:令人困惑的部分(1)》:
https://jacobbuckman/post/tensorflow-the-confusing-parts-1/
Dino Causevic—《TensorFlow入门:机器学习教程》:
https://toptal/machine-learning/tensorflow-machine-learning-tutorial
《Python TensorFlow教程:构建一个神经网络》:
http://adventuresinmachinelearning/python-tensorflow-tutorial
TensorFlow教程:
Jason Brownlee—《掌握机器学习》:
https://machinelearningmastery/start-here/
示例
代码示例
https://github/aymericdamien/TensorFlow-Examples
https://github/MorvanZhou/Tensorflow-Tutorial
工具
Google Colaboratory (Colab):
https://colab.research.google/notebooks/welcome.ipynb#scrollTo=9wi5kfGdhK0R
COLAB笔记本
Colab提供了一个基于Jupyter的交互式Python笔记本,它具有两大优势:
可以使用它来生成HTML / CSS的可视化免费的GPU计算时间
Colab是一个用来共享研究、分享学习新工具心得的平台。
Tensorboard:
https://tensorflow.org/programmers_guide/summaries_and_tensorboard
https://github/tensorflow/tensorboard
Tensorboard正在展示交叉熵图
Tensorboard 3D图
Tensorboard是一种可视化机器学习模型的工具。 旨在解决黑盒问题。 它对以下几方面的内容有较大的作用:
设计模型的结构调试可视化性能生成结果图
一些技巧
结合使用Tensorboard和Colab:
https://stackoverflow/questions/47818822/can-i-use-tensorboard-with-google-colab
如果你发现了Tensorboard和Colab的价值所在,那么你就值得花费一定的时间学习如何讲它们结合使用。
社区
Announcements & Jokes:
https://reddit/r/MachineLearning/
Slack:
https://slofile/slack/ai-researchers
Discord:
https://discordlist.me/join/167811324590424065/
书籍
神经网络与深度学习(免费在线图书):
http://neuralnetworksanddeeplearning/
深度学习(在线图书):
http://deeplearningbook.org/
Goodreads上流行的数据科学书籍:
https://goodreads/shelf/show/data-science
更多资源
机器学习研究:
https://distill.pub/
arXiv:
人工智能:https://arxiv.org/list/cs.AI/new计算机视觉和模式识别:https://arxiv.org/list/cs.CV/new机器学习:https://arxiv.org/list/cs.LG/new
职业
《如何成为数据科学家》:
https://datasciencecentral/profiles/blogs/how-to-become-a-data-scientist-for-free
求职
linkedIn:https://linkedin/jobs/machine-learning-jobs/
AngelList: https://angel.co/machine-learning/jobs
新智元AI WORLD 2018大会【早鸟票】
开售!
新智元将于9月20日在北京国家会议中心举办AI WORLD 2018 大会,邀请机器学习教父、CMU教授 Tom Mitchell,迈克思·泰格马克,周志华,陶大程,陈怡然等AI领袖一起关注机器智能与人类命运。
大会官网:
http://aiworld2018/
即日起到8月19日,新智元限量发售若干早鸟票,与全球AI领袖近距离交流,见证全球人工智能产业跨越发展。
活动行购票链接:http://huodongxing/event/6449053775000活动行购票二维码:
- ?
TensorFlow入门教程(一): 变量,图与会话的基本用法
羊笑南
展开
本教程由深度学习中文社区(Studydl)持续发布与更新.
在前面的文章中,我们讲解了怎么配置深度学习服务器从零开始搭建深度学习服务器:TensorFlow + PyTorch + Torch, 希望大家能多动手自己实践实践. 在后面的时间里我们会推出一系列的TensorFlow与PyTorch的入门教程, 希望大家多多转发与关注.
基本使用
使用 TensorFlow, 你必须明白 TensorFlow:
使用图 (graph) 来表示计算任务.在被称之为 会话 (Session)的上下文 (context) 中执行图.使用 tensor 表示数据.通过 变量 (Variable) 维护状态.使用 feed 和 fetch 可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据.
综述
TensorFlow 是一个编程系统, 使用图来表示计算任务. 图中的节点被称之为 op(operation 的缩写). 一个 op 获得 0 个或多个 Tensor, 执行计算, 产生 0 个或多个 Tensor. 每个 Tensor 是一个类型化的多维数组. 例如, 你可以将一小组图像集表示为一个四维浮点数数组, 这四个维度分别是 [batch, height, width, channels].
一个 TensorFlow 图描述了计算的过程. 为了进行计算, 图必须在会话里被启动. 会话将图的 op 分发到诸如 CPU 或 GPU 之类的设备上, 同时提供执行 op 的方法. 这些方法执行后, 将产生的 tensor 返回. 在 Python 语言中, 返回的 tensor 是 numpy ndarray对象; 在 C 和 C++ 语言中, 返回的 tensor 是tensorflow::Tensor实例.
计算图
TensorFlow 程序通常被组织成一个构建阶段和一个执行阶段. 在构建阶段, op 的执行步骤 被描述成一个图. 在执行阶段, 使用会话执行执行图中的 op.
例如, 通常在构建阶段创建一个图来表示和训练神经网络, 然后在执行阶段反复执行图中的训练 op.
TensorFlow 支持 C, C++, Python 编程语言. 目前, TensorFlow 的 Python 库更加易用, 它提供了大量的辅助函数来简化构建图的工作, 这些函数尚未被 C 和 C++ 库支持.
三种语言的会话库 (session libraries) 是一致的.
构建图
构建图的第一步, 是创建源 op (source op). 源 op 不需要任何输入, 例如常量 (Constant). 源 op 的输出被传递给其它 op 做运算.
Python 库中, op 构造器的返回值代表被构造出的 op 的输出, 这些返回值可以传递给其它 op 构造器作为输入.
TensorFlow Python 库有一个默认图 (default graph), op 构造器可以为其增加节点. 这个默认图对 许多程序来说已经足够用了. 阅读 Graph 类文档来了解如何管理多个图.
import tensorflow as tf# 创建一个常量 op, 产生一个 1x2 矩阵. 这个 op 被作为一个节点# 加到默认图中.## 构造器的返回值代表该常量 op 的返回值.matrix1 = tf.constant([[3., 3.]])# 创建另外一个常量 op, 产生一个 2x1 矩阵.matrix2 = tf.constant([[2.],[2.]])# 创建一个矩阵乘法 matmul op , 把 'matrix1' 和 'matrix2' 作为输入.# 返回值 'product' 代表矩阵乘法的结果.product = tf.matmul(matrix1, matrix2)
默认图现在有三个节点, 两个 constant() op, 和一个matmul() op. 为了真正进行矩阵相乘运算, 并得到矩阵乘法的结果, 你必须在会话里启动这个图.
在一个会话中启动图
构造阶段完成后, 才能启动图. 启动图的第一步是创建一个 Session对象, 如果无任何创建参数, 会话构造器将启动默认图.欲了解完整的会话 API, 请阅读Session 类.
# 启动默认图.sess = tf.Session()# 调用 sess 的 'run()' 方法来执行矩阵乘法 op, 传入 'product' 作为该方法的参数. # 上面提到, 'product' 代表了矩阵乘法 op 的输出, 传入它是向方法表明, 我们希望取回# 矩阵乘法 op 的输出.## 整个执行过程是自动化的, 会话负责传递 op 所需的全部输入. op 通常是并发执行的.# # 函数调用 'run(product)' 触发了图中三个 op (两个常量 op 和一个矩阵乘法 op) 的执行.## 返回值 'result' 是一个 numpy `ndarray` 对象.result = sess.run(product)print result# ==> [[ 12.]]# 任务完成, 关闭会话.sess.close()
Session对象在使用完后需要关闭以释放资源. 除了显式调用 close 外, 也可以使用 "with" 代码块来自动完成关闭动作, 因为百家号的编辑器里引用时无法在头部添加空格,所以以后使用_代替两个空格,以后系列教程里同此操作.
with tf.Session() as sess:__result = sess.run([product]) __print result
在实现上, TensorFlow 将图形定义转换成分布式执行的操作, 以充分利用可用的计算资源(如 CPU 或 GPU). 一般你不需要显式指定使用 CPU 还是 GPU, TensorFlow 能自动检测. 如果检测到 GPU, TensorFlow 会尽可能地利用找到的第一个 GPU 来执行操作.
如果机器上有超过一个可用的 GPU, 除第一个外的其它 GPU 默认是不参与计算的. 为了让 TensorFlow 使用这些 GPU, 你必须将 op 明确指派给它们执行. with...Device语句用来指派特定的 CPU 或 GPU 执行操作:
with tf.Session() as sess:__with tf.device("/gpu:0"):____matrix1 = tf.constant([[3., 3.]])____matrix2 = tf.constant([[2.],[2.]])____product = tf.matmul(matrix1, matrix2)____...
设备用字符串进行标识. 目前支持的设备包括:
"/cpu:0": 机器的 CPU."/gpu:0": 机器的第一个 GPU, 如果有的话."/gpu:1": 机器的第二个 GPU, 以此类推.
阅读使用GPU章节, 了解 TensorFlow GPU 使用的更多信息.
交互式使用
文档中的 Python 示例使用一个会话 Session来启动图, 并调用 Session.run()方法执行操作.
为了便于使用诸如 IPython 之类的 Python 交互环境, 可以使用 InteractiveSession代替 Session类, 使用Tensor.eval()和 Operation.run()方法代替 Session.run(). 这样可以避免使用一个变量来持有会话.
# 进入一个交互式 TensorFlow 会话.import tensorflow as tfsess = tf.InteractiveSession()x = tf.Variable([1.0, 2.0])a = tf.constant([3.0, 3.0])# 使用初始化器 initializer op 的 run() 方法初始化 'x' x.initializer.run()# 增加一个减法 sub op, 从 'x' 减去 'a'. 运行减法 op, 输出结果 sub = tf.sub(x, a)print sub.eval()# ==> [-2. -1.]
Tensor
TensorFlow 程序使用 tensor 数据结构来代表所有的数据, 计算图中, 操作间传递的数据都是 tensor. 你可以把 TensorFlow tensor 看作是一个 n 维的数组或列表. 一个 tensor 包含一个静态类型 rank, 和 一个 shape. 想了解 TensorFlow 是如何处理这些概念的, 参见 Rank, Shape, 和Type.
变量
Variables for more details. 变量维护图执行过程中的状态信息. 下面的例子演示了如何使用变量实现一个简单的计数器. 参见 变量 章节了解更多细节.
# 创建一个变量, 初始化为标量 0.state = tf.Variable(0, name="counter")# 创建一个 op, 其作用是使 state 增加 1one = tf.constant(1) new_value = tf.add(state, one) update = tf.assign(state, new_value)# 启动图后, 变量必须先经过`初始化` (init) op 初始化,# 首先必须增加一个`初始化` op 到图中.init_op = tf.initialize_all_variables()# 启动图, 运行 opwith tf.Session() as sess: __# 运行 'init' op__sess.run(init_op) __# 打印 'state' 的初始值 __print sess.run(state) __# 运行 op, 更新 'state', 并打印 'state' __for _ in range(3): ____sess.run(update) ____print sess.run(state)
# 输出:# 0# 1# 2# 3
代码中assign()操作是图所描绘的表达式的一部分, 正如add()操作一样. 所以在调用run()执行表达式之前, 它并不会真正执行赋值操作.
通常会将一个统计模型中的参数表示为一组变量. 例如, 你可以将一个神经网络的权重作为某个变量存储在一个tensor中. 在训练过程中, 通过重复运行训练图, 更新这个tensor.
Fetch
为了取回操作的输出内容, 可以在使用Session对象的run()调用执行图时, 传入一些 tensor, 这些 tensor会帮助你取回结果. 在之前的例子里, 我们只取回了单个节点state, 但是你也可以取回多个tensor:
input1 = tf.constant(3.0) input2 = tf.constant(2.0) input3 = tf.constant(5.0) intermed = tf.add(input2, input3) mul = tf.mul(input1, intermed)with tf.Session(): __result = sess.run([mul, intermed]) __print result__# 输出:__# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]
需要获取的多个tensor 值,在 op 的一次运行中一起获得(而不是逐个去获取 tensor。
Feed
上述示例在计算图中引入了tensor, 以常量或变量的形式存储. TensorFlow 还提供了feed机制, 该机制 可以临时替代图中的任意操作中的 tensor 可以对图中任何操作提交补丁, 直接插入一个 tensor.
feed 使用一个 tensor 值临时替换一个操作的输出结果. 你可以提供 feed 数据作为 run() 调用的参数. feed 只在调用它的方法内有效, 方法结束, feed 就会消失. 最常见的用例是将某些特殊的操作指定为 "feed" 操作, 标记的方法是使用 tf.placeholder() 为这些操作创建占位符.
input1 = tf.placeholder(tf.types.float32) input2 = tf.placeholder(tf.types.float32) output = tf.mul(input1, input2)with tf.Session() as sess: __print sess.run([output], feed_dict={input1:[7.], input2:[2.]})__# 输出:__# [array([ 14.], dtype=float32)]
如果没有正确提供 feed , placeholder() 操作将会产生错误.
- ?
TensorFlow进阶教程(一):使用TFHub模型10行代码快速开发AI程序
羊戎
展开
本教程由深度学习中文社区(Studydl)持续发布与更新, 本系列其余教程地址见文章末尾.
在前面的章节中, 我们介绍了一些TensorFlow的入门教程, 以及在最近两节中我们介绍了一下怎么在Android与浏览器上使用TensorFlow开发深度学习应用. 从这期开始我们将推出TensorFlow进阶教程, 主要讲解一些TensorFlow的使用技巧. 在后面的时间里我们还会推出一系列的PyTorch的入门教程, 希望大家多多转发与关注。
在深度学习研究过程中, 共享预训练模型使开发人员可以根据不用领域、不用场景进行自定义,而无需访问计算资源或用于训练原始模型的数据。例如,NASNet 需要数千小时进行模型训练。通过共享学习的权重,模型开发人员可以使其他人更容易重用和构建工作。
TensorFlow Hub 专门为机器学习开发者提供第三方库。在本文中,我们将简单介绍 TensorFlow Hub 中常用的几种库。TensorFlow Hub 是一个平台,主要被用于发布、发现和重用机器学习模块。一个模块,我们指的是 TensorFlow 图形的一个独立部分及其权重,可以在其他类似任务中重复使用。通过重用模块,开发人员可以使用较小的数据集训练模型,提升泛化能力或简单地加速训练。让我们看几个例子来说明这一点。
图像再训练
作为第一个例子,让我们看一下可以用来训练图像分类器的技术,仅从少量训练数据开始。现代图像识别模型具有数百万个参数,当然,从头开始训练需要大量标记数据和计算能力。使用称为图像重新训练的技术,您可以使用更少量的数据训练模型,并且使用更少的计算时间。如下所示:
基本思想是重用现有的图像识别模块从图像中提取特征,然后在这些特征之上训练新的分类器。如您所见,在构造 TensorFlow 图时,可以从 URL(或从文件系统路径)实例化 TensorFlow Hub 模块。
TensorFlow Hub 上有多种模块供您选择,包括 NASNet,MobileNet(包括最近的 V2),Inception,ResNet 等。要使用模块,请导入 TensorFlow Hub,然后将模块的 URL 复制/粘贴到代码中。
每个模块都定义了接口,我们可以在很少或根本不了解其内部的情况下以可替换的方式使用。在这种情况下,此模块有一个方法可用于获取预期的图像大小。作为开发人员,您只需要提供正确形状的一批图像,并调用模块以获取特征表示。此模块负责为您预处理图像,因此您可以在一个步骤中直接从一批图像转到特征表示。从这里开始,您可以在这些基础上学习线性模型或其他类型的分类器。
请注意我们正在使用的模块由 Google 托管,并且已经进行版本控制。模块可以像普通的 Python 函数一样应用,以构建图形的一部分。一旦导出到磁盘,模块就是自包含的,并且可以被其他人使用而无需访问用于创建和训练它的代码和数据。
文本分类
我们来看看第二个例子。想象一下,你想训练一个模型,将电影评论分类为正面或负面,从少量的训练数据开始(比如几百个正面和负面的电影评论)。由于您的示例数量有限,因此您决定利用先前在更大的语料库中训练的单词嵌入数据集。如下所示:
和以前一样,我们首先选择一个模块。TensorFlow Hub 有多种文本模块供您探索,包括各种语言的神经网络语言模型,以及在维基百科上训练的 Word2vec,以及在 Google 新闻上训练的 NNLM。
在这种情况下,我们将使用一个模块进行字嵌入。上面的代码下载一个模块,用它来预处理一个句子,然后获取每个标记的嵌入。
这意味着您可以直接从数据集中的句子转换为适合分类器的格式。该模块负责对句子进行标记,以及其他逻辑。预处理逻辑和嵌入都封装在一个模块中,可以更轻松地试验各种单词嵌入数据集或不同的预处理策略,而无需大幅更改代码。
通用句子编码器
我们还分享了一个新的 TensorFlow Hub 模块!下面是使用 Universal Sentence Encoder 的示例。它是一个句子级嵌入模块,适用于各种数据集。它擅长语义相似性,自定义文本分类和聚类。
与图像再训练一样,需要相对较少的标记数据使模块适应特定的任务。如下所示:
其他模块
TensorFlow Hub 不仅仅有图像和文本分类库。在网站上,你还可以找到几个 Progressive GAN 模型和 Google Landmarks Deep Local Features.
TensorFlow入门系列教程文章地址:
只需以下两步就可获取到零基础入门教教程啦:
回到文章最上方点击关注按钮关注我的百家号,方便接收最新教程.点击标题下方的头像位置, 就可进入我的主页, 里面就有我之前发布的TensorFlow入门系列教程啦.
目前已发布的TensorFlow入门教程列表:
- ?
TensorFlow极简教程:创建、保存和恢复机器学习模型
应雪青
展开
选自Github机器之心编译参与:Jane W、李泽南
TensorFlow 是一个由谷歌发布的机器学习框架,在这篇文章中,我们将阐述 TensorFlow 的一些本质概念。相信你不会找到比本文更简单的介绍。
TensorFlow 机器学习范例——Naked Tensor
链接:https://github/jostmey/NakedTensor?bare
在每个例子中,我们用一条直线拟合一些数据。使用梯度下降(gradient descent)确定最适合数据的线的斜率和 y 截距的值。如果你不知道梯度下降,请查看维基百科:
https://en.wikipedia.org/wiki/Gradient_descent
创建所需的变量后,数据和线之间的误差是可以被定义(计算)的。定义的误差被嵌入到优化器(optimizer)中。然后启动 TensorFlow,并重复调用优化器。通过不断迭代最小化误差来达到数据与直线的最佳拟合。
按照顺序阅读下列脚本:
serial.pytensor.pybigdata.py
Serial.py
这个脚本的目的是说明 TensorFlow 模型的基本要点。这个脚本使你更容易理解模型是如何组合在一起的。我们使用 for 循环来定义数据与线之间的误差。由于定义误差的方式为循环,该脚本以序列化(串行)计算的方式运行。
Tensor.py
这个脚本比 serial.py 更进一步,虽然实际上这个脚本的代码行更少。代码的结构与之前相同,唯一不同的是这次使用张量(tensor)操作来定义误差。使用张量可以并行(parallel)运行代码。
每个数据点被看作是来自独立同分布的样本。因为每个数据点假定是独立的,所以计算也是独立的。当使用张量时,每个数据点都在分隔的计算内核上运行。我们有 8 个数据点,所以如果你有一个有八个内核的计算机,它的运行速度应该快八倍。
BigData.py
你现在距离专业水平仅有一个流行语之遥。我们现在不需要将一条线拟合到 8 个数据点,而是将一条线拟合到 800 万个数据点。欢迎来到大数据时代。
代码中有两处主要的修改。第一点变化是簿记(bookkeeping),因为所有数据必须使用占位符(placeholder)而不是实际数据来定义误差。在代码的后半部分,数据需要通过占位符馈送(feed)入模型。第二点变化是,因为我们的数据量是巨大的,在给定的任意时间我们仅将一个样本数据传入模型。每次调用梯度下降操作时,新的数据样本将被馈送到模型中。通过对数据集进行抽样,TensorFlow 不需要一次处理整个数据集。这样抽样的效果出奇的好,并有理论支持这种方法:
https://en.wikipedia.org/wiki/Stochastic_gradient_descent
理论上需要满足一些重要的条件,如步长(step size)必须随每次迭代而缩短。不管是否满足条件,这种方法至少是有效的。
结论
当你运行脚本时,你可能看到怎样定义任何你想要的误差。它可能是一组图像和卷积神经网络(convolutional neural network)之间的误差。它可能是古典音乐和循环神经网络(recurrent neural network)之间的误差。它让你的想象力疯狂。一旦定义了误差,你就可以使用 TensorFlow 进行尝试并最小化误差。
希望你从这个教程中得到启发。
需求
Python3 (https://python.org/)TensorFlow (https://tensorflow.org/)NumPy (http://numpy.org/)
TensorFlow:保存/恢复和混合多重模型
在第一个模型成功建立并训练之后,你或许需要了解如何保存与恢复这些模型。继续之前,也可以阅读这个 Tensorflow 小入门:
https://blog.metaflow.fr/tensorflow-a-primer-4b3fa0978be3#.wxlmweb8h
你有必要了解这些信息,因为了解如何保存不同级别的代码是非常重要的,这可以避免混乱无序。
如何实际保存和加载
保存(saver)对象
可以使用 Saver 对象处理不同会话(session)中任何与文件系统有持续数据传输的交互。构造函数(constructor)允许你控制以下 3 个事物:
目标(target):在分布式架构的情况下用于处理计算。可以指定要计算的 TF 服务器或「目标」。图(graph):你希望会话处理的图。对于初学者来说,棘手的事情是:TF 中总存在一个默认的图,其中所有操作的设置都是默认的,所以你的操作范围总在一个「默认的图」中。配置(config):你可以使用 ConfigProto 配置 TF。查看本文最后的链接资源以获取更多详细信息。
Saver 可以处理图的元数据和变量数据的保存和加载(又称恢复)。它需要知道的唯一的事情是:需要使用哪个图和变量?
默认情况下,Saver 会处理默认的图及其所有包含的变量,但是你可以创建尽可能多的 Saver 来控制你想要的任何图或子图的变量。这里是一个例子:
import tensorflow as tf
import os
dir = os.path.dirname(os.path.realpath(__file__))
# First, you design your mathematical operations
# We are the default graph scope
# Let's design a variable
v1 = tf.Variable(1. , name="v1")
v2 = tf.Variable(2. , name="v2")
# Let's design an operation
a = tf.add(v1, v2)
# Let's create a Saver object
# By default, the Saver handles every Variables related to the default graph
all_saver = tf.train.Saver()
# But you can precise which vars you want to save under which name
v2_saver = tf.train.Saver({"v2": v2})
# By default the Session handles the default graph and all its included variables
with tf.Session() as sess:
# Init v and v2
sess.run(tf.global_variables_initializer())
# Now v1 holds the value 1.0 and v2 holds the value 2.0
# We can now save all those values
all_saver.save(sess, dir + '/data-all.chkp')
# or saves only v2
v2_saver.save(sess, dir + '/data-v2.chkp')
如果查看你的文件夹,它实际上每创建 3 个文件调用一次保存操作并创建一个检查点(checkpoint)文件,我会在附录中讲述更多的细节。你可以简单理解为权重被保存到 .chkp.data 文件中,你的图和元数据被保存到 .chkp.meta 文件中。
恢复操作和其它元数据
一个重要的信息是,Saver 将保存与你的图相关联的任何元数据。这意味着加载元检查点还将恢复与图相关联的所有空变量、操作和集合(例如,它将恢复训练优化器)。
当你恢复一个元检查点时,实际上是将保存的图加载到当前默认的图中。现在你可以通过它来加载任何包含的内容,如张量、操作或集合。
import tensorflow as tf
# Let's load a previously saved meta graph in the default graph
# This function returns a Saver
saver = tf.train.import_meta_graph('results/model.ckpt-1000.meta')
# We can now access the default graph where all our metadata has been loaded
graph = tf.get_default_graph()
# Finally we can retrieve tensors, operations, collections, etc.
global_step_tensor = graph.get_tensor_by_name('loss/global_step:0')
train_op = graph.get_operation_by_name('loss/train_op')
hyperparameters = tf.get_collection('hyperparameters')
恢复权重
请记住,实际的权重只存在于一个会话中。这意味着「恢复」操作必须能够访问会话以恢复图内的权重。理解恢复操作的最好方法是将其简单地当作一种初始化。
with tf.Session() as sess:
# To initialize values with saved data
saver.restore(sess, 'results/model.ckpt.data-1000-00000-of-00001')
print(sess.run(global_step_tensor)) # returns 1000
在新图中使用预训练图
现在你知道了如何保存和加载,你可能已经明白如何去操作。然而,这里有一些技巧能够帮助你走得更快。
一个图的输出可以是另一个图的输入吗?
是的,但有一个缺点:我还不知道使梯度流(gradient flow)在图之间容易传递的一种方法,因为你将必须评估第一个图,获得结果,并将其馈送到下一个图。
这样一直下去是可以的,直到你需要重新训练第一个图。在这种情况下,你将需要将输入梯度馈送到第一个图的训练步骤……
我可以在一个图中混合所有这些不同的图吗?
是的,但你需要对命名空间(namespace)倍加小心。好的一点是,这种方法简化了一切:例如,你可以加载预训练的 VGG-16,访问图中的任何节点,嵌入自己的操作和训练整个图!
如果你只想微调(fine-tune)节点,你可以在任意地方停止梯度来避免训练整个图。
import tensorflow as tf
# Load the VGG-16 model in the default graph
vgg_saver = tf.train.import_meta_graph(dir + 'gg/resultsgg-16.meta')
# Access the graph
vgg_graph = tf.get_default_graph()
# Retrieve VGG inputs
self.x_plh = vgg_graph.get_tensor_by_name('input:0')
# Choose which node you want to connect your own graph
output_conv =vgg_graph.get_tensor_by_name('conv1_2:0')
# output_conv =vgg_graph.get_tensor_by_name('conv2_2:0')
# output_conv =vgg_graph.get_tensor_by_name('conv3_3:0')
# output_conv =vgg_graph.get_tensor_by_name('conv4_3:0')
# output_conv =vgg_graph.get_tensor_by_name('conv5_3:0')
# Stop the gradient for fine-tuning
output_conv_sg = tf.stop_gradient(output_conv) # It's an identity function
# Build further operations
output_conv_shape = output_conv_sg.get_shape().as_list()
W1 = tf.get_variable('W1', shape=[1, 1, output_conv_shape[3], 32], initializer=tf.random_normal_initializer(stddev=1e-1))
b1 = tf.get_variable('b1', shape=[32], initializer=tf.constant_initializer(0.1))
z1 = tf.nn.conv2d(output_conv_sg, W1, strides=[1, 1, 1, 1], padding='SAME') + b1
a = tf.nn.relu(z1)
附录:更多关于 TF 数据生态系统的内容
我们在这里谈论谷歌,他们主要使用内部构建的工具来处理他们的工作,所以数据保存的格式为 ProtoBuff 也是不奇怪的。
协议缓冲区
协议缓冲区(Protocol Buffer/简写 Protobufs)是 TF 有效存储和传输数据的常用方式。
我不在这里详细介绍它,但可以把它当成一个更快的 JSON 格式,当你在存储/传输时需要节省空间/带宽,你可以压缩它。简而言之,你可以使用 Protobufs 作为:
一种未压缩的、人性化的文本格式,扩展名为 .pbtxt一种压缩的、机器友好的二进制格式,扩展名为 .pb 或根本没有扩展名
这就像在开发设置中使用 JSON,并且在迁移到生产环境时为了提高效率而压缩数据一样。用 Protobufs 可以做更多的事情,如果你有兴趣可以查看教程
整洁的小技巧:在张量流中处理 protobufs 的所有操作都有这个表示「协议缓冲区定义」的「_def」后缀。例如,要加载保存的图的 protobufs,可以使用函数:tf.import_graph_def。要获取当前图作为 protobufs,可以使用:Graph.as_graph_def()。
文件的架构
回到 TF,当保存你的数据时,你会得到 5 种不同类型的文件:
「检查点」文件「事件(event)」文件「文本 protobufs」文件一些「chkp」文件一些「元 chkp」文件
现在让我们休息一下。当你想到,当你在做机器学习时可能会保存什么?你可以保存模型的架构和与其关联的学习到的权重。你可能希望在训练或事件整个训练架构时保存一些训练特征,如模型的损失(loss)和准确率(accuracy)。你可能希望保存超参数和其它操作,以便之后重新启动训练或重复实现结果。这正是 TensorFlow 的作用。
在这里,检查点文件的三种类型用于存储模型及其权重有关的压缩后数据。
检查点文件只是一个簿记文件,你可以结合使用高级辅助程序加载不同时间保存的 chkp 文件。元 chkp 文件包含模型的压缩 Protobufs 图以及所有与之关联的元数据(集合、学习速率、操作等)。chkp 文件保存数据(权重)本身(这一个通常是相当大的大小)。如果你想做一些调试,pbtxt 文件只是模型的非压缩 Protobufs 图。最后,事件文件在 TensorBoard 中存储了所有你需要用来可视化模型和训练时测量的所有数据。这与保存/恢复模型本身无关。
下面让我们看一下结果文件夹的屏幕截图:
一些随机训练的结果文件夹的屏幕截图
该模型已经在步骤 433,858,1000 被保存了 3 次。为什么这些数字看起来像随机?因为我设定每 S 秒保存一次模型,而不是每 T 次迭代后保存。chkp 文件比元 chkp 文件更大,因为它包含我们模型的权重pbtxt 文件比元 chkp 文件大一点:它被认为是非压缩版本!
TF 自带多个方便的帮助方法,如:
在时间和迭代中处理模型的不同检查点。它如同一个救生员,以防你的机器在训练结束前崩溃。
注意:TensorFlow 现在发展很快,这些文章目前是基于 1.0.0 版本编写的。
参考资源
http://stackoverflow/questions/38947658/tensorflow-saving-into-loading-a-graph-from-a-file
http://stackoverflow/questions/34343259/is-there-an-example-on-how-to-generate-protobuf-files-holding-trained-tensorflow?rq=1
http://stackoverflow/questions/39468640/tensorflow-freeze-graph-py-the-name-save-const0-refers-to-a-tensor-which-doe?rq=1
http://stackoverflow/questions/33759623/tensorflow-how-to-restore-a-previously-saved-model-python
http://stackoverflow/questions/34500052/tensorflow-saving-and-restoring-session?noredirect=1&lq=1
http://stackoverflow/questions/35687678/using-a-pre-trained-word-embedding-word2vec-or-glove-in-tensorflow
https://github/jtoy/awesome-tensorflow
- ?
什么是TensorFlow,TensorFlow教程
沈白筠
展开
阅读本文以了解更多关于TensorFlow的知识,并了解如何在项目中使用它。
TensorFlow教程
目的:在今天的TensorFlow教程中,我们将学习什么是TensorFlow,它在哪里使用,它的不同特性,TensorFlow应用程序,最新版本及其优缺点,以及如何在项目中使用它。
TensorFlow教程|什么是TensorFlow
TensorFlow的历史
DistBelief是TensorFlow在升级之前被调用的,它是在2011年作为一个基于深度学习神经网络的专有系统构建的。DistBelief的源代码经过修改,被做成了一个更好的基于应用程序的库,2015年,它被称为tensorflow。
TensorFlow是什么?
TensorFlow是一个强大的面向数据流的机器学习库,由谷歌的Brain Team创建,于2015年开源。它被设计成易于使用和广泛应用于数字和神经网络的问题以及其他领域。
本质上,TensorFlow是一个用于处理复杂数学问题的低级工具包,它针对的是那些知道自己在做什么的研究人员,以构建实验学习体系结构,并将其转化为运行中的软件。
它可以被认为是一个编程系统,在这个系统中,你将计算表示为图形。图中的节点表示数学运算,边缘表示它们之间通信的多维数据数组(张量)。
最新版本
TensorFlow的最新版本是1.7.0,可以在tensorflow.org上找到。它的设计理念是深度学习,但它适用于更广泛的问题。
关于张量
现在,顾名思义,它提供了在张量上定义函数并自动计算其导数的原语。
张量是一种高维数组,用于计算机编程,以数字的形式表示大量的数据。在互联网上还有其他n - d数组库,就像Numpy一样,但TensorFlow是独立的,因为它提供了创建张量函数并自动计算导数的方法。
TensorFlow教程
其他的用途
您可以在其上构建其他的机器学习算法,比如决策树或k近邻。下面是一个由TensorFlow组成的生态系统:
TensorFlow生态系统。
从上面的描述可以看出,TensorFlow可集成性良好,具有包括GPU处理、python和Cpp在内的依赖关系,您也可以使用它与docker等容器软件集成。
TensorBoard
TensorBoard是一套可视化工具,是TensorFlow的一种简单解决方案,它由创建者提供,允许您可视化图形,并使用其他数据(如图像)来绘制图形的定量度量。
操作
TensorFlow在各种平台上运行,安装是linux操作系统,安装很简单。它可以使用pip或conda环境进行安装。这些应用程序不仅支持深度学习,还支持其他形式的机器学习,比如强化学习。强化学习把你带入目标导向的任务中,比如赢得视频游戏,或者帮助机器人在不平衡的环境中行走。
TensorFlow应用程序
有无数的机器学习的应用和TensorFlow允许您去探索他们中的大多数包括情绪分析,谷歌翻译,文本摘要和,图像识别,它被世界各地的大公司,包括Airbnb,eBay,Dropbox,Snapchat,Twitter,Uber,SAP、高通、IBM、英特尔、当然,谷歌、Facebook、Instagram,亚马逊用于各种目的。
TensorFlow特性
TensorGlow具有用于Matlab和c++的api,并且具有广泛的语言支持。随着时间的推移,研究人员正在努力让它变得更好,最近,在最新的TensorFlow峰会上,TensorFlow.js是一个用于培训和部署机器学习模型的javascript库,并且在tensorflow官网上可以使用一个开源浏览器集成平台,在那里您可以看到在修改超参数时发生的实时变化。
TensorFlow优势
TensorFlow有一个响应性结构,您可以很容易地将图形的每个部分可视化。平台的灵活性,这意味着它是模块化的,有些部分可以独立而其他人合并。它可以在CPU和GPU上轻松地进行分布式计算。它具有自动分化功能,它可以利用基于梯度的机器学习算法,也就是说,你可以通过对其他值来计算值的导数,从而得出图表扩展的结果。它支持线程、异步计算和队列。它是可定制的和开放源码的。TensorFlow局限性
如果在相同的范围内导入GPU内存,则会与Theano发生冲突。
不支持OpenCL
需要有高级微积分和线性代数知识以及对机器学习的了解。
结论
TensorFlow是一个很好的库,可以在创建深度学习网络时对数据进行数值和图形计算,是谷歌Search、谷歌Translate Translate、谷歌Photos等应用最广泛的库。人们使用机器学习做了许多令人惊叹的事情,其中包括与医疗保健相关的应用、电影推荐引擎、音乐、个性化广告和社交媒体情绪挖掘等。随着机器学习和人工智能的进步让人难以置信,TensorFlow是帮助实现这些目标的工具。
- ?
从框架优缺点说起,这是一份TensorFlow入门极简教程
纸谢
展开
随着 TensorFLow 在研究及产品中的应用日益广泛,很多开发者及研究者都希望能深入学习这一深度学习框架。而在昨天机器之心发起的框架投票中,2144 位参与者中有 1441 位都在使用 TensorFlow 框架,是所有框架中使用率最高的。但 TensorFLow 这种静态计算图有一定的学习成本,因此也阻挡了很多初学者入坑。本文介绍了学习 TensorFlow 的系列教程,旨在通过简单的理论与实践帮助初学者一步步掌握 TensorFlow 的编程技巧。这一系列教程分为 6 部分,从为什么选择 TensorFlow 到卷积神经网络的实现,介绍了初学者所需要的技能。机器之心在本文介绍了 PyTorch 和 Caffe 等深度学习框架的优缺点及 TensorFlow 基础,包括静态计算图、张量、TensorBoard 可视化和模型参数的保存等。
机器之心此前也介绍过很多 TensorFlow 的学习资源,读者可结合这些资源阅读该系列教程:
学习了!谷歌今日上线基于 TensorFlow 的机器学习速成课程(中文版)机器之心 GitHub 项目:从零开始用 TensorFlow 搭建卷积神经网络教程 | 从零开始:TensorFlow 机器学习模型快速部署指南分布式 TensorFlow 入坑指南:从实例到代码带你玩转多机器深度学习三天速成!香港科技大学 TensorFlow 课件分享TensorFlow 从基础到实战:一步步教你创建交通标志分类神经网络为什么选择 TensorFlow?在本文中,我们将对比当前最流行的深度学习框架(包括 Caffe、Theano、PyTorch、TensorFlow 和 Keras),帮助你为应用选择最合适的框架。
1. Caffe:第一个主流产品级深度学习库,于 2014 年由 UC Berkeley 启动。
优点:
快速支持 GPU漂亮的 Matlab 和 Python 接口缺点:
不灵活。在 Caffe 中,每个节点被当做一个层,因此如果你想要一种新的层类型,你需要定义完整的前向、后向和梯度更新过程。这些层是网络的构建模块,你需要在无穷无尽的列表中进行选择。(相反,在 TensorFlow 中,每个节点被当做一个张量运算例如矩阵相加、相乘或卷积。你可以轻易地定义一个层作为这些运算的组合。因此 TensorFlow 的构建模块更小巧,允许更灵活的模块化。)需要大量的非必要冗长代码。如果你希望同时支持 CPU 和 GPU,你需要为每一个实现额外的函数。你还需要使用普通的文本编辑器来定义你的模型。真令人头疼!几乎每个人都希望程序化地定义模型,因为这有利于不同组件之间的模块化。有趣的是,Caffe 的主要架构师现在在 TensorFlow 团队工作。专一性。仅定位在计算机视觉(但做得很不错)。不是以 Python 编写!如果你希望引入新的变动,你需要在 C++和 CUDA 上编程(对于更小的变动,你可以使用它的 Python 和 Matlab 接口)。糟糕的文档。安装比较困难!有大量的依赖包。只有少量种类的输入格式,仅有一种输出格式 HDF5(虽然你总是可以使用它的 Python/C++/Matlab 接口来运行,并从中得到输出数据)。不适用于构建循环网络。2. Theano:由蒙特利尔大学研究团队构建。Theano 的顶层构建了数值开源深度库,包括 Keras、Lasagne 和 Blocks。Yoshua Bengio 在 2017 年 9 月 28 日宣布,Theano 的开发将终止。因此实际上 Theano 已死!
优点:
计算图的抽象很漂亮(可媲美 TensorFlow)为 CPU 和 GPU 都做了优化很好地适应数值优化任务高级封装(Keras、Lasagne)缺点:
原始的 Theano 只有比较低级的 APIimport numpy for _ in range(T): h = torch.matmul(W, h) + b大型模型可能需要很长的编译时间不支持多 GPU错误信息可能没有帮助(有时候令人懊恼)3. Pytorch:2017 年 1 月,Facebook 将 Python 版本的 Torch 库(用 Lua 编写)开源。
优点:
提供动态计算图(意味着图是在运行时生成的),允许你处理可变长度的输入和输出,例如,在使用 RNN 时非常有用。另一个例子是,在 PyTorch 中,可以使用标准 Python 语法编写 for 循环语句。大量预训练模型大量易于组合的模块化组件易于编写自己的图层类型,易于在 GPU 上运行「Tensorboard」缺少一些关键功能时,「Losswise」可以作为 Pytorch 的替代品缺点:
正式文档以外的参考资料/资源有限无商业支持4. Tensorflow:由较低级别的符号计算库(如 Theano)与较高级别的网络规范库(如 Blocks 和 Lasagne)组合而成。
优点:
由谷歌开发、维护,因此可以保障支持、开发的持续性。巨大、活跃的社区网络训练的低级、高级接口「Tensorboard」是一款强大的可视化套件,旨在跟踪网络拓扑和性能,使调试更加简单。用 Python 编写(尽管某些对性能有重要影响的部分是用 C++实现的),这是一种颇具可读性的开发语言支持多 GPU。因此可以在不同的计算机上自由运行代码,而不必停止或重新启动程序比基于 Theano 的选项更快的模型编译编译时间比 Theano 短TensorFlow 不仅支持深度学习,还有支持强化学习和其他算法的工具。缺点:
计算图是纯 Python 的,因此速度较慢图构造是静态的,意味着图必须先被「编译」再运行5. Keras:Keras 是一个更高级、对用户最友好的 API,具有可配置的后端,由 Google Brain 团队成员 Francis Chollet 编写和维护。
优点:
提供高级 API 来构建深度学习模型,使其易于阅读和使用编写规范的文档大型、活跃的社区位于其他深度学习库(如 Theano 和 Tensorflow,可配置)之上使用面向对象的设计,因此所有内容都被视为对象(如网络层、参数、优化器等)。所有模型参数都可以作为对象属性进行访问。例如:
model.layers[3].output 将提供模型的第三层model.layers[3].weights 是符号权重张量的列表缺点:
由于用途非常普遍,所以在性能方面比较欠缺与 Tensorflow 后端配合使用时会出现性能问题(因为并未针对其进行优化),但与 Theano 后端配合使用时效果良好不像 Tensorflow 或 PyTorch 那样灵活TensorFlow 基础TensorFlow 是一种采用数据流图(data flow graphs),用于数值计算的开源软件库。其中 Tensor 代表传递的数据为张量(多维数组),Flow 代表使用计算图进行运算。数据流图用「结点」(nodes)和「边」(edges)组成的有向图来描述数学运算。「结点」一般用来表示施加的数学操作,但也可以表示数据输入的起点和输出的终点,或者是读取/写入持久变量(persistent variable)的终点。边表示结点之间的输入/输出关系。这些数据边可以传送维度可动态调整的多维数据数组,即张量(tensor)。
计算图与会话学习 Tensorflow 的第一步是了解它的主要特色——「计算图」方法。基本上所有的 Tensorflow 代码都包含两个重要部分:
1. 创建「计算图」,表示计算的数据流
2. 运行「会话」,执行图中的运算
事实上,TensorFlow 将计算的定义与其执行分开。这两个部分将在以下各节中详细说明。在此之前,请记住第一步是导入 Tensorflolibrary!
import tensorflow as tf这样,Python 就可以访问 TensorFlow 的所有类、方法和符号。使用此命令,TensorFlow 库将在别名「tf」下导入,以便以后我们可以使用它而不必每次键入其全称「TensorFlow」。
tensorflow 教程
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
初入新手村 — 演示者视图的操作步骤 0102
-
初入新手村 — 鼠标的交互的方法 0103
-
初入新手村 — 如何快速访问工具栏 0104
-
初入新手村 — 文件选项卡、保存等基础 0105
-
第二关 :内容整理与处理 — 导航区操作技巧 0201
-
第三关 :文字工具与段落 — 如何给你的文字加特效 0301
-
文字工具与段落— 段落工具使用 0302
-
第四关:绘图与形状效果 — 基本形状的绘制方法 0401
-
绘图与形状效果 — 给你的图形加特效 0402
-
绘图与形状效果 — 快速排列多种图形 0403
-
第五关:合并形状与图标 — 用好合并形状轻松获得更多创意图形 0501
-
第六关:图片的神奇 — 教你PPT如何实现抠图 0601
-
图片的神奇 — 使用图片裁剪让图片为你所用 0602
-
第七关:表格与逻辑图表 — 教你画一个简洁大方的表格 0701
-
表格与逻辑图表 — SmartArt快速生成逻辑图表 0702
-
表格与逻辑图表 — 一招SmartArt走遍天下 0703
-
第八关:形象化市场数据 — PPT中数据图表怎么做?0801
-
形象化市场数据 — 教你做好看的条形图和柱状图 0802
-
形象化市场数据 — 饼图的美化技巧 0803
-
第十关:终成商务演示高手
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101
-
第一关 :初入新手村 — 工具选项卡操作演示 0101