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 年推出的。它们是AI加速器专用集成电路(ASIC)。但是,它们仍然非常昂贵。
除此之外,我们希望将我们的模型部署到不同的平台,如云、嵌入式系统(IoT)或将其集成到其他语言中。这就是为什么 TensorFlow 生态系统看起来像这样:
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 更易于安装和配置。
如果您使用的是 Anaconda,可以按照以下步骤安装 TensorFlow:
- 通过运行以下命令创建 conda 环境 “tensorflow”:
conda create -n tensorflow pip pythnotallow=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 TensorFlow 工作流
大多数 TensorFlow 代码都遵循以下工作流程:
- 导入数据集
- 使用其他列扩展数据集以描述数据
- 选择模型类型
- 训练
- 评估模型的准确性
- 使用模型预测结果
4.2 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 中选择一个估算器。
Estimator 类的对象封装用于构建 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 的训练方法。
# 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))
5. Keras – TensorFlow 的高级 API
目前,Keras 是 TensorFlow 的默认高级 API。在本文中,我们稍后将使用这个 API 来构建一个简单的神经网络,所以让我们稍微探讨一下它是如何工作的。根据问题的类型,我们可以为要构建的神经网络使用各种层。
从本质上讲,Keras 提供了不同类型的层 (tensorflow.keras.layers),我们需要将它们连接到一个有意义的图形中,以解决我们的问题。在构建深度学习模型时,我们可以通过多种方式执行此 API:
- 使用 Sequential 类
- 使用函数式 API
- 模型子类化
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
输出如下所示:
正如我们所看到的,物种或输出的类型为 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'])
这意味着我们将以概率的形式获得输出。让我们来训练这个神经网络。为此,我们使用 fit 方法并传递准备好的训练数据:
model.fit(X_train, y_train, epochs=300, batch_size=10)
epoch 的数量定义了整个训练集将通过网络的时间。这可以持续几分钟,输出如下所示:
我们完成了。我们创建了一个模型并对其进行了训练。现在,我们必须对其进行评估,看看我们是否有好的结果。
6.3 评估和新预测
评估是通过调用评估方法完成的。我们向它提供测试数据,它对每个样本进行预测,并将其与实际结果进行比较:
scores = model.evaluate(X_test, y_test)
print("\nAccuracy: %.2f%%" % (scores[1]*100))
在这种特殊情况下,我们得到了 95.56% 的准确率:
45/45 [==============================] - 0s 756us/step
Accuracy: 95.56%
最后,让我们得到一些预测:
prediction = model.predict(X_test)
prediction1 = pd.DataFrame({'IRIS1':prediction[:,0],'IRIS2':prediction[:,1], 'IRIS3':prediction[:,2]})
prediction1.round(decimals=4).head()
以下是我们得到的结果与实际结果的比较:
如果我们正在使用真实数据处理其他数据集,那么这些好的结果将是可疑的。我们可以怀疑发生了“过度拟合”。但是,在这个简单的数据集上,我们将接受这些结果作为好的结果。