【深度学习与TensorFlow 2.0】入门篇

:由于毕业论文须要用到相关知识,借着 TF 2.0 发布的时机,从新捡起深度学习。在此,也推荐一下优达学城与 TensorFlow 合做发布的TF 2.0入门课程,下面的例子就来自该课程。html

原文发布于博客园:http://www.javashuo.com/article/p-dqwntdax-by.htmlpython

本文中全部代码都在文末第二个连接中,转载请注明出处!git

 

机器学习与深度学习


深度学习是机器学习的一个分支,当下也是该领域发展最快、最受关注的一个分支。上周刚刚公布的2018年图灵奖就颁发给了对深度学习的发展作出了重要贡献的三位科学家:Yoshua Bengio、Geoffrey Hinton 和 Yann LeCun。相对于传统的机器学习算法,深度学习最大的区别在于:在训练的过冲中,由神经网络自主学习数据的表示,而不须要人工作特征工程。github

以前写了多篇与机器学习有关的博文,如下几篇与深度学习有关,能够帮助理解基础知识:算法

  1. 【机器学习】一些基本概念及符号系统
  2. 【机器学习】代价函数(cost function)
  3. 【机器学习】逻辑回归(Logistic Regression)
  4. 【机器学习】神经网络实现异或(XOR)

由于深度学习是机器学习的一个分支,与传统的机器学习方法有很是多的类似之处。归纳以下:编程

  • 解决的主要问题:分类(二分类或多分类),回归,聚类;
  • 学习的基本过程:在有监督学习(分类和回归问题)中,都是输入“数据 + 标签(答案)”,得到“算法”(从数据到答案的某种映射关系);
  • 训练过程都是对代价函数的优化过程;
  • 都面临过拟合的挑战,所以都须要正则化方面的技术;
  • 均可以使用梯度降低法来优化参数.

固然深度学习中,也有一些有别于传统机器学习的主题:网络

  • 网络的结构:层数,每一层的神经单元数;
  • 激活函数:做用于隐藏层神经元,使得数据的变化过程从线性到非线性;
  • 反向传播:用于多层神经网络中偏差(或梯度)从网络的输出层向输入层传播;
  • 其余特殊网络结构:CNN 中的卷积、长短时间记忆网络、编码器和解码器等.

 

多层感知机


多层感知机(multilayer percepton, MLP)也叫深度前馈网络或前馈神经网络,是典型的深度学习模型。其目的是近似某个函数$f^*$。当前馈神经网络被拓展成包含反馈链接时,它们被称为循环神经网络(recurrent neural network, RNN)。机器学习

关于多层感知机的基础知识,能够参考我以前的博客——【机器学习】神经网络实现异或(XOR),或下面的两篇博主"python27"的学习笔记:函数

 

一个简单的例子


虽然接触到深度学习的知识已经很长时间了,可是在平时遇到分类或是回归相关的问题,仍是会优先选择传统的机器学习算法。有时候是由于数据量比较小,可是还有一个比较重要的缘由是本身实践太少,对于深度学习这个工具,用起来还不顺手。以前学习的时候,在TensorFlow、Pytouch和Keras之间很难作出选择。如今TF 2.0借鉴Keras中的API风格,既保持了性能的优点,也更加简单易学。加上最近刚刚发布的课程,所以就决定选择TF 2.0做为本身之后练习深度学习算法的工具。工具

 

将摄氏度转换成华氏度

温度的不一样单位之间的转换有明确的定义,知道其中一种单位的温度值能够经过下面的公式精确的计算出另外一种单位下的温度值。

 $$ f = c \times 1.8 + 32 $$

 若是咱们已知该公式,将该公式写成一个函数,输入为$c$,输出为$f$,那么这就是一个入门级的编程练习题。

可是假如咱们如今知道几个数值对,即输入和答案,该公式并不知道。此时就能够利用机器学习的方法,求出一个近似的从$c$到$f$的映射关系。

下面是代码:

 1 from __future__ import absolute_import, division, print_function
 2 import tensorflow as tf
 3 tf.logging.set_verbosity(tf.logging.ERROR)
 4 
 5 import numpy as np
 6 
 7 # 输入的摄氏温度以及其对应的华氏温度,前面两个故意写错了
 8 celsius_q    = np.array([-40, -10,  0,  8, 15, 22,  38],  dtype=float)
 9 fahrenheit_a = np.array([-40,  14, 32, 46, 59, 72, 100],  dtype=float)
10 
11 for i,c in enumerate(celsius_q):
12   print("{} degrees Celsius = {} degrees Fahrenheit".format(c, fahrenheit_a[i]))
13 
14 # 输入后链接了只有一个神经单元的隐藏层
15 l0 = tf.keras.layers.Dense(units=1, input_shape=[1])
16 
17 # 将网络层添加到序列模型中
18 model = tf.keras.Sequential([l0])
19 
20 # 编译神经网络模型
21 model.compile(loss='mean_squared_error',
22               optimizer=tf.keras.optimizers.Adam(0.1))
23 
24 # 训练模型
25 history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
26 print("Finished training the model")

在这个例子中,包括如下要素:

  1. 训练数据:一共有7个样本(输入 + 答案),有两个样本的值不许确(在实际项目中,有多是由于测量或记录致使的偏差);
  2. 层(layers):神经网络是以层为基本组成单位的,每层有两个最基本的参数units和activation,分别表示该层神经单元的个数和激活函数(这里没有设置第二个参数就表示不对该层的神经单元进行任何变换);
  3. 层的类型:层的不一样类型,表明了层之间不一样的链接方式,这里使用的是全链接层(Dense),表示各层之间全部点都直接相连;
  4. 模型:组织不一样“层”的方式,这里使用的序列模型(Sequential)按照层的顺序从输入到输出叠加各个层;
  5. 编译(compile):训练以前必须编译,在编译的时候须要指定两个很是重要的参数——loss和optimizer,loss就是代价函数,optimizer是训练模型的方法;
  6. 训练模型(fit):必要参数为输入数据,对于的标签(答案),迭代次数(epochs)等.

上面15行和18行一般会写在一块儿:

model = tf.keras.Sequential([
  tf.keras.layers.Dense(units=1, input_shape=[1])
])

 

模型训练的过程当中,损失函数的值会随着训练次数发生变化。这些变化由fit函数返回,记录在history中。画出来以下:

import matplotlib.pyplot as plt
plt.xlabel('Epoch Number')
plt.ylabel("Loss Magnitude")
plt.plot(history.history['loss'])

图1:loss随着训练次数的增长而减少

这个模型很是简单,若是不算输入层,整个模型只有1层:输入层链接了只有一个神经单元的层l0,该层处理以后的数据直接做为输出值。

所以该模型的网络结构以下:

图2:上面例子中神经网络的结构

上图中的l0只有一个神经单元,另外还有一个偏置单元(输入值x上方的蓝色点,除了输入层外,每层默认都会有一个做用于该层的偏置单元)。所以,从输入到输出能够表示为:

$$y = x*w + b$$

神经网络的结构本质上是对最终模型的一种假设,这里的假设刚好与真实模型彻底相同:线性模型,两个参数。可是在彻底不知道真实模型的状况下,大部分时候模型的容量可能都远超过了真实模型,表如今参数多(模型的自由度大),结构复杂,添加了非线性变换的激活函数,所以容易致使过拟合。

训练完成后,能够查看模型各层的参数(偏置单元虽然画在了输入层上方,但仍是算做l0层的参数):

print("These are the layer variables: {}".format(l0.get_weights()))

下面是输出:

These are the layer variables: [array([[1.8220955]], dtype=float32), array([29.117624], dtype=float32)]

第一个值(1.822,x的参数)与真实值1.8很是接近,第二个值(29.118,偏置单元的取值)与真实值32也比较接近。因而可知,虽然训练数据中包含两个偏差比较大的点,可是最终模型仍是比较准确的找到了这两组数据之间的基本规律:$y = 1.82x + 29.12$

训练好模型以后,可使用下面的方法预测新值:

print(model.predict([100.0]))

输出为"[[211.32718]]",该值与真实值212很是接近。

以上就是假设在不知道温度两种单位之间的转换公式的状况下,经过很是简单的神经网络学习到两组数据之间关系的过程。

学习到与真实的转换公式如此接近的结果,强烈依赖于最开始设定的网络结构(一种先验,对最终模型的假设)。在不知道真实模型的状况下,一般会假设一个比较复杂的网络结构。此时模型参数多,自由度大,模型的容量和搜索空间也是远超过了真实模型,此时真实模型必定被包含其中,但不必定能找到,或者找到很是接近全局最优解的局部最优解。

下面是另外一种网络结构的假设:

 1 l0 = tf.keras.layers.Dense(units=4, input_shape=[1])  
 2 l1 = tf.keras.layers.Dense(units=4)  
 3 l2 = tf.keras.layers.Dense(units=1)  
 4 model = tf.keras.Sequential([l0, l1, l2])
 5 model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(0.1))
 6 model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
 7 print("Finished training the model")
 8 print(model.predict([100.0]))
 9 print("Model predicts that 100 degrees Celsius is: {} degrees Fahrenheit".format(model.predict([100.0])))
10 print("These are the l0 variables: {}".format(l0.get_weights()))
11 print("These are the l1 variables: {}".format(l1.get_weights()))
12 print("These are the l2 variables: {}".format(l2.get_weights()))

输出以下:

Finished training the model
[[211.74747]]
Model predicts that 100 degrees Celsius is: [[211.74747]] degrees Fahrenheit
These are the l0 variables: [array([[ 0.45070484, -0.611826  ,  0.1898421 ,  0.0913914 ]],
      dtype=float32), array([ 3.4355907, -3.5666099, -2.7151687,  3.45835  ], dtype=float32)]
These are the l1 variables: [array([[ 0.22470416,  1.2858697 ,  0.81416523,  0.359274  ],
       [ 0.38035178, -0.86285967,  0.34824482, -0.30044237],
       [-0.16603428, -0.5080208 , -0.27835467, -0.6047108 ],
       [-0.5545173 ,  0.9019376 ,  0.19518667, -0.2925983 ]],
      dtype=float32), array([-3.1969943,  3.4892511,  1.7240645,  3.4472196], dtype=float32)]
These are the l2 variables: [array([[-0.30633917],
       [ 1.4714689 ],
       [ 0.31956905],
       [ 0.41886073]], dtype=float32), array([3.3831294], dtype=float32)]

能够看到新模型预测100摄氏度的结果也很是接近其真实的华氏温度。此时模型的结构以下:

图3:第二个模型的网络结构

不算输入层,这个模型一共有3层。其中两个隐藏层各自含有4个神经单元(蓝色点表示每层的偏置单元)。除了输入层外,其余每一个神经单元的取值都由直接与之相连的点(及对应的参数)决定:例如l1层从上往下数第2个橙色点的取值由上一层4个点(及对应的参数)的取值和偏置单元的取值决定。能够归纳的表示以下:

$$y' = x·w + b$$

其中$x$表示上一层的全部神经单元构成的向量,$w$是链接$y'$与上一层全部单元的参数,$b$是偏置单元。由于这里仍是没有设置激活函数,所以每一层中的各个单元都是上一层全部单元取值的线性组合。

虽然第二个模型也能很好的完成预测任务,可是与真实的转换公式之间差别巨大,并且可解释性也变差了。

 

 

Reference


https://cn.udacity.com/course/intro-to-tensorflow-for-deep-learning--ud187

https://github.com/OnlyBelter/examples/blob/master/courses/udacity_intro_to_tensorflow_for_deep_learning/l02c01_celsius_to_fahrenheit.ipynb

相关文章
相关标签/搜索