在这篇文章中,我们将介绍。
6.用TensorFlow、Keras和Python构建神经网络
1.TensorFlow基础知识
那么,TensorFlow是如何工作的?好吧,首先,他们的整个解决方案是围绕着张量,即TensorFlow的原始单元。TensorFlow使用一个张量数据结构来表示所有的数据。
在数学上,张量是描述其他几何对象之间的线性关系的几何对象。在TesnsorFlow中,它们是多维数组或数据,即矩阵。好吧,没有那么简单,但这是整个张量的概念在线性代数中更深入,我现在想去看看。
总之,我们可以把张量看作是n维数组,使用它可以轻松有效地进行矩阵运算。例如,在下面的代码中,我们定义了两个常数张量,并将一个值加到另一个值上。
import tensorflow as tf
const1 = tf.constant([[1,2,3], [1,2,3]]);
const2 = tf.constant([[3,4,5], [3,4,5]]);
result = tf.add(const1, const2);
with tf.Session() as sess:
output = sess.run(result)
print(output)
常量,正如你已经知道的,是不会改变的值。然而,TensorFlow有丰富的API,这是很好的 记载了使用它,我们可以定义其他类型的数据,如变量。
import tensorflow as tf
var1 = tf.Variable([[1, 2], [1, 2]], name="variable1")
var2 = tf.Variable([[3, 4], [3, 4]], name="variable2")
result = tf.matmul(var1, var2)
with tf.Session() as sess:
output = sess.run(result)
print(output)
除了张量之外,TensorFlow还使用数据流图。图中的节点代表数学运算,而边代表它们之间交流的张量。
2.TensorFlow 生态系统
当然,我们并不想只做简单的算术运算,我们想用这个库来构建预测器、分类器、生成模型、神经网络等等。一般来说,当你要构建这样的解决方案时,我们必须经过 几个步骤:
- 分析 ,对数据进行预处理
- 建立 和 训练 一个模型(机器学习模型,神经网络,...)。
- 评估 模型
- 作出新的预测
由于这些模型的训练可能是一个昂贵而漫长的过程,我们可能想使用不同的机器来做这个。在CPU上训练这些模型可能需要相当长的时间,所以使用GPU总是更好的选择。
训练这些模型的最快选择是 张量处理单元 或 TPU。这些是谷歌早在2016年推出的。它们是一个人工智能加速器的特定应用集成电路(ASIC)。然而,它们仍然相当昂贵。
除此以外,我们希望将我们的模型部署到不同的平台,如云、嵌入式系统(物联网)或将其整合到其他语言中。这就是为什么 TensorFlow 生态系统看起来像这样。

我们可以看到,在这个 生态系统中,涵盖了开发这些解决方案的所有这些主要要点。说到Python,我们通常使用 numpy 和 pandas等库来分析和处理数据。然后我们使用这些数据将其推送到我们所建立的模型中。
这有点超出了本文的范围,而且数据分析本身就是一个话题。然而, TensorFlow 正在给我们提供一些 模块 ,利用这些模块我们可以做一些预处理和特征工程。除此之外,它还提供了 数据集 (tensorflow.datasets),我们可以用它来训练我们的一些自定义解决方案和进行一般的研究。
TensorFlow 最重要的部分是 TensorFlow Hub。在那里我们可以找到许多模块和 低级别的API ,我们可以使用。在这些核心模块之上,我们可以找到高级API-- Keras。我们可以说,2.0版本的道路是在 TensorFlow 1.10.0中铺设的,当时 Keras 被纳入默认的高级API。
在此之前,Keras是一个独立的库, tensorflow.contrib 模块被用于此目的。随着TensorFlow 1.10.0的推出,我们得到消息, tensorflow.contrib 模块将很快被 删除 , Keras 接管。而这也是TensorFlow 2.0的重点之一, ,以简化使用和清理API。事实上,1.0中的许多API要么被转移,要么被完全删除。例如, tf.app 和 tf.flags 不再存在, tf.* 的一些不太常用的函数被转移到其他模块。

除了我们将在本文后面使用的这个高级API之外,还有几个 预训练的 模型。这些模型是在一些数据集上训练出来的,可以为你的解决方案定制。
在机器学习解决方案的开发中,这种方法也被称为 转移学习。转移学习在人工智能工程师中越来越受欢迎,因为它加快了这个过程。当然,你可以选择使用这些预训练的模型作为开箱即用的解决方案。
对于 TensorFlow ,也有几个 分布 选项,所以我们可以选择我们要训练模型的平台。这是在安装框架的过程中决定的,所以我们将在后面的章节中更多地研究它。我们可以选择 TensorFlow ,在CPU、GPU或TPU上运行的分布。
最后,一旦我们建立了我们的模型,我们可以保存它。这个模型可以并入不同 平台上的其他应用程序。在这里,我们进入了 的部署世界。需要注意的是,建立一个模型是一个完全不同于其他应用开发的过程。一般来说,数据科学家建立这些模型并保存它们。后来这些模型被应用程序的业务逻辑组件所调用。
3.TensorFlow的安装和设置
TensorFlow为广泛的语言提供API,如Python、C++、Java、Go、Haskell和R(以第三方库的形式)。此外,它还支持不同类型的操作系统。在这篇文章中,我们将在Windows 10上使用Python,所以只涉及该平台的安装过程。
TensorFlow只支持 Python 3.5以上版本因此,请确保你的系统上安装了这些版本之一。对于其他操作系统和语言,你可以查看 官方安装指南.我们需要知道的另一件事是我们系统的硬件配置。在安装TensorFlow方面有两个选择:
- 仅支持CPU的TensorFlow。
- 支持GPU的TensorFlow。
如果你的系统有一个NVIDIA® GPU,那么你可以安装支持GPU的TensorFlow。当然,GPU版本更快,但CPU更容易安装和配置。

如果你使用的是 蟒蛇安装TensorFlow可以按照以下步骤进行。
-
通过运行命令创建一个conda环境 "tensorflow"。
conda create -n tensorflow pip python=3.5 -
通过发布命令激活创建的环境。
activate tensorflow -
调用命令将TensorFlow安装在你的环境中。对于CPU版本,运行这个命令。
pip install --ignore-installed --upgrade tensorflow对于GPU版本,运行该命令。
pip install --ignore-installed --upgrade tensorflow-gpu
当然,你也可以使用 "native pip "安装TensorFlow。对于CPU版本运行。
pip3 install --upgrade tensorflow
对于GPU TensorFlow版本,运行命令。
pip3 install --upgrade tensorflow-gpu
酷,现在我们已经安装了我们的TensorFlow。让我们来运行一下我们要解决的问题。
4.使用预定义的TensorFlow模块
4.1 虹膜数据集分类问题
虹膜数据集,以及 MNIST数据集这可能是模式识别文献中最著名的数据集之一。它是机器学习分类问题的 "Hello World "例子。它最早是由罗纳德-费希尔在1936年提出的。他是英国统计学家和植物学家,他在《分类学问题中多重测量的使用 》这篇论文中使用了这个例子*,* 这篇论文至今还经常被引用。该数据集包含3个类,每个类50个实例。每个类指的是一种鸢尾花植物的类型。Iris setosa,Iris virginica, andIris versicolor。第一个类与其他两个类是可以线性分离的,但后两个类之间是不能线性分离的。每条记录有五个属性:
- 萼片长度(厘米
- 萼片宽度(厘米
- 花瓣长度(cm)
- 花瓣宽度(厘米
- 类别*(鸢尾花Setosa*,鸢尾花virginica, 鸢尾花versicolor)。
我们要创建的神经网络的目标是根据其他属性来预测鸢尾花的类别。这意味着它需要创建一个模型,来描述属性值和类别之间的关系。

4.2 TensorFlow工作流程
大多数的TensorFlow代码都遵循这个工作流程:
- 导入数据集
- 用额外的列来扩展数据集以描述数据
- 选择模型的类型
- 训练
- 评估模型的准确性
- 使用该模型预测结果
如果你按照我之前 博文训练和评估过程是开发任何人工神经网络的重要部分。这些过程通常在两个数据集上完成,一个用于训练,另一个用于测试训练后的网络的准确性。通常,我们只得到一组数据,我们需要将其分成两个独立的数据集,一个用于训练,另一个用于测试。这个比例通常是80%对20%。这一次,我们已经完成了这项工作。你可以下载训练集和测试集的代码,这些代码伴随着这篇文章。
4.3 Python代码
让我们潜心研究吧!我们需要做的第一件事是导入数据集,并对其进行解析。为此,我们将使用另一个Python库--Pandas。这是另一个开源库,为Python提供易于使用的数据结构和数据分析工具。
# Import `tensorflow` and `pandas`
import tensorflow as tf
import pandas as pd
COLUMN_NAMES = [
'SepalLength',
'SepalWidth',
'PetalLength',
'PetalWidth',
'Species'
]
# Import training dataset
training_dataset = pd.read_csv('iris_training.csv', names=COLUMN_NAMES, header=0)
train_x = training_dataset.iloc[:, 0:4]
train_y = training_dataset.iloc[:, 4]
# Import testing dataset
test_dataset = pd.read_csv('iris_test.csv', names=COLUMN_NAMES, header=0)
test_x = test_dataset.iloc[:, 0:4]
test_y = test_dataset.iloc[:, 4]
正如你所看到的,首先我们使用read_csv 函数将数据集导入本地变量,然后我们将输入 (train_x, test_x) 和预期输出 (train_y, test_y) 分开,创建四个独立的矩阵。我们准备了将用于训练和测试的数据。现在,我们需要定义特征列,这将有助于我们的神经网络。
# Setup feature columns
columns_feat = [
tf.feature_column.numeric_column(key='SepalLength'),
tf.feature_column.numeric_column(key='SepalWidth'),
tf.feature_column.numeric_column(key='PetalLength'),
tf.feature_column.numeric_column(key='PetalWidth')
]
我们现在需要选择我们要使用的模型。在我们的问题中,我们正试图根据属性数据来预测鸢尾花的类别。这就是为什么我们要选择TensorFlow API中的一个估计器。
估算器类的一个对象封装了建立TensorFlow图和运行TensorFlow会话的逻辑。为了这个目的,我们将使用 DNNClassifier 。我们将添加两个隐藏层,每个层有十个神经元。

# Build Neural Network - Classifier
classifier = tf.estimator.DNNClassifier(
feature_columns=columns_feat,
# Two hidden layers of 10 nodes each.
hidden_units=[10, 10],
# The model is classifying 3 classes
n_classes=3)
之后,我们将用从训练数据集中挑选的数据训练我们的神经网络。首先,我们将定义训练函数。这个函数需要通过扩展训练集和创建多个批次来为神经网络提供数据。
如果训练实例的顺序是随机的,那么训练效果最好。这就是为什么调用了shuffle函数。总而言之,train_function通过从训练数据集中随机抽取数据并将其反馈给DNNClassifier的train方法,使用传递的训练数据集创建数据批。
# Define train function
def train_function(inputs, outputs, batch_size):
dataset = tf.data.Dataset.from_tensor_slices((dict(inputs), outputs))
dataset = dataset.shuffle(1000).repeat().batch(batch_size)
return dataset.make_one_shot_iterator().get_next()
# Train the Model.
classifier.train(
input_fn=lambda:train_function(train_x, train_y, 100),
steps=1000)
最后,我们调用evaluate函数,它将评估我们的神经网络,并给出网络的准确性。
# Define evaluation function
def evaluation_function(attributes, classes, batch_size):
attributes=dict(attributes)
if classes is None:
inputs = attributes
else:
inputs = (attributes, classes)
dataset = tf.data.Dataset.from_tensor_slices(inputs)
assert batch_size is not None, "batch_size must not be None"
dataset = dataset.batch(batch_size)
return dataset.make_one_shot_iterator().get_next()
# Evaluate the model.
eval_result = classifier.evaluate(
input_fn=lambda:evaluation_function(test_x, test_y, 100))
当我们运行这段代码时,我的神经网络的准确率为0.93,这是很不错的。在这之后,我们可以使用单一数据调用我们的分类器,并获得预测结果。
5.Keras - TensorFlow的高级API
今天, Keras 是 TensorFlow的默认高级API。在这篇文章中,我们将使用这个API来构建一个简单的神经网络,所以让我们来探索一下它的功能。根据问题的类型,我们可以为我们想要建立的神经网络使用各种层。
从本质上讲,Keras提供了不同类型的层 (tensorflow.keras.layer),我们需要将其连接成一个有意义的图,从而解决我们的问题。在构建深度学习模型时,我们有几种方法可以完成这个API:
- 使用序贯类
- 使用函数式API
- 模型子类化

第一种方法是最简单的一种。我们使用 Sequential 类,它实际上是一个 占位符 ,用于层,我们按照我们想要的顺序添加层。当我们想以最快的方式构建神经网络时,我们可能想选择这种方法, 最快的 。
Keras层也有很多类型,我们可以选择。最基本的一种,也是我们在本文中要使用的一种,叫做 Dense。 它有许多 选项 ,用于设置输入、 激活函数 ,等等。除了 Dense之外,Keras API还 为 卷积神经网络、 循环神经网络等提供了不同类型的层。这已经超出了本篇文章的范围。因此,让我们看看如何使用 Sequential和Dense构建一个 Neural Network 。
6.用TensorFlow、Keras和Python构建神经网络
为了解决这个问题,我们将采取我们在之前的一个章节中定义的步骤:
- 分析和预处理数据
- 建立和训练一个模型
- 评估模型
- 作出新的预测
6.1 数据分析和预处理
数据分析本身就是一个话题。在这里,我们不会深入研究 特征工程 和分析,但我们将观察一些基本步骤。
- 单变量分析 - 分析每个特征的类型和性质。
- 缺失数据处理 - 检测缺失数据并制定相关策略。
- 相关性分析 - 互相比较特征。
- 分割数据 - 因为我们有一组信息,所以我们需要制作一个单独的数据集来训练神经网络,并制作一组数据来评估神经网络。
利用我们在这个分析过程中收集的信息,我们可以在创建模型本身的过程中采取适当的行动。首先,我们 ,导入 数据。
COLUMN_NAMES = [
'SepalLength',
'SepalWidth',
'PetalLength',
'PetalWidth',
'Species'
]
data = pd.read_csv('iris_data.csv', names=COLUMN_NAMES, header=0)
data.head()
正如你所看到的,我们使用 Pandas 库来做这件事,并且我们还打印出前五行的数据。下面是它的样子。

一旦完成了这些,我们想看看每个特征的 性质是什么 。为此,我们也可以使用 Pandas 。
data.dtypes
输出结果是这样的。

我们可以看到 Species 或输出的类型是 int64。然而,我们了解到这不是我们想要的结果。我们希望这个特征是一个 的分类变量。这意味着我们需要对这个数据进行一些修改,再次使用 Pandas。
data['Species'] = data['Species'].astype("category")
data.dtypes
一旦这样做了,我们就检查一下我们的数据集中是否有 缺失的数据 。这是用这个函数完成的。
print(data.isnull().sum())
这个调用的输出是:

缺失的数据对我们的神经网络来说可能是一个问题。如果我们的数据集中有缺失的数据,我们需要定义一个 策略 ,如何处理它。一些方法是,用特征的 平均值 或其 最大值 来代替缺失值。
然而,并没有什么灵丹妙药,有时不同的策略会带来比其他策略更好的结果。好了,开始进行 关联分析。在这个步骤中,我们要检查特征之间的关系。使用 Pandas 和 Seaborn 模块,我们能够得到一个图像,显示一些特征之间的依赖程度的矩阵-- 相关矩阵。
corrMatt = data[["SepalLength","SepalWidth","PetalLength","PetalWidth","Species"]].corr()
mask = np.array(corrMatt)
mask[np.tril_indices_from(mask)] = False
fig,ax= plt.subplots()
fig.set_size_inches(20,10)
sn.heatmap(corrMatt, mask=mask,vmax=.8, square=True,annot=True)
下面是这个矩阵的样子。

我们想通过这个相关矩阵找到 Spices 和一些特征之间的关系。正如你所看到的,这些数值在-1和1之间。我们的目标是那些数值接近1或-1的,这意味着这些特征有太多的共同点, ,即太多的 对彼此的影响 。
如果我们有这种情况,建议只为一个模型提供这些特征中的一个。这样我们就可以避免出现我们的模型给出过于乐观(或者说是错误的) 预测的情况。然而,在这个数据集中,我们几乎没有任何信息,所以如果我们删除所有的依赖关系,我们将没有数据。
最后,让我们把数据分成 训练 和 测试 集。因为客户通常会给我们一大块数据,我们需要留下一些数据用于测试。通常情况下,这个比例是80:20。在这篇文章中,我们将使用70:30,只是为了玩玩。为此,我们使用 SciKit Learn 库中的一个函数。
output_data = data["Species"]
input_data = data.drop("Species",axis=1)
X_train, X_test, y_train, y_test = train_test_split(input_data, output_data, test_size=0.3, random_state=42)
最后,我们有四个变量,包含 用于训练和测试的 输入 数据,以及用于训练和测试的输出 数据。我们现在可以建立我们的模型了。
6.2 构建和训练一个神经网络
我们需要一个相当简单的神经网络来进行这个 分类。在这里,我们使用了模型子分类的方法,但你也可以尝试其他方法。下面是 IrisClassifier 类的样子。
class IrisClassifier(Model):
def __init__(self):
super(IrisClassifier, self).__init__()
self.layer1 = Dense(10, activation='relu')
self.layer2 = Dense(10, activation='relu')
self.outputLayer = Dense(3, activation='softmax')
def call(self, x):
x = self.layer1(x)
x = self.layer2(x)
return self.outputLayer(x)
model = IrisClassifier()
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss='categorical_crossentropy',
metrics=['accuracy'])
它是一个小型的神经网络,有两层10个神经元。最后一层有3个神经元,因为鸢尾花有3个类别。另外,在最后一层, 激活函数 使用 softmax。
这意味着,我们将得到一个 概率形式的输出 。让我们来 训练 这个神经网络。为此,我们使用拟合 方法并通过准备好的训练数据。
model.fit(X_train, y_train, epochs=300, batch_size=10)
epochs的数量 ,定义了整个训练集将通过网络的时间。这可以持续几分钟,输出看起来像这样。

然后我们就完成了。我们创建了一个模型并对其进行了训练。现在,我们必须评估它,看看我们是否有好的结果。
6.3 评估和新预测
评估 ,通过调用 evaluate 方法来完成 。我们向它提供测试数据,它对每个样本进行预测并与实际结果进行比较。
scores = model.evaluate(X_test, y_test)
print("\nAccuracy: %.2f%%" % (scores[1]*100))
在这个特定的案例中,我们得到了95.56%的准确率。
45/45 [==============================] - 0s 756us/step
最后,让我们得到一些预测结果。
prediction = model.predict(X_test)
prediction1 = pd.DataFrame({'IRIS1':prediction[:,0],'IRIS2':prediction[:,1], 'IRIS3':prediction[:,2]})
prediction1.round(decimals=4).head()
下面是我们与真实结果的比较结果。

如果我们在其他的真实数据集上工作,这些好的结果就很可疑了。我们可以怀疑发生了 "过度拟合"。然而,在这个简单的数据集上,我们将接受这些结果作为良好的结果。
7.TensorFlow与PyTorch
TensorFlow/Keras和PyTorch是最流行的深度学习框架。在上一篇文章中,我们写到了PyTorch。一般来说,区别在于速度(用PyTorch训练的模型更快),PyTorch感觉,嗯......更像pythonic,所以说。PyTorch也是纯粹的面向对象的,而TensorFlow是有选择的。另外,TensorFlow在行业中占主导地位,而PyTorch在研究中很受欢迎。

总结
神经网络已经存在了很长时间,几乎所有的重要概念都是在20世纪70年代或80年代引入的。阻止整个领域起飞的问题是,当时我们没有强大的计算机和GPU来运行这些程序。现在,我们不仅可以做到这一点,而且谷歌通过公开提供这个伟大的工具--TensorFlow,使神经网络得到普及。
谢谢你的阅读!