TensorFlow 2入门指南,初学者必备!
什么是Tensorflow?
TensorFlow是谷歌推出的深度学习框架,于2019年发布了第二版。 它是世界上最著名的深度学习框架之一,被行业专家和研究人员广泛使用。
Tensorflow v1难以使用和理解,因为它的Pythonic较少,但是随着Keras发行的v2现在与Tensorflow.keras完全同步,它易于使用,易学且易于理解。
请记住,这不是有关深度学习的文章,所以我希望您了解深度学习的术语及其背后的基本思想。
我们将使用非常著名的数据集IRIS数据集探索深度学习的世界。
废话不多说,我们直接看看代码。
导入和理解数据集
from sklearn.datasets import load_iris iris = load_iris()
现在,这个 iris 是一个字典。 我们可以使用下面的代码查看键值
>>> iris.keys() dict_keys([‘data’, ‘target’, ‘frame’, ‘target_names’, ‘DESCR’, ‘feature_names’, ‘filename’])
因此,我们的数据在 data 键中,目标在 targe 键中,依此类推。 如果要查看此数据集的详细信息,可以使用 iris[ ['DESCR']。
现在,我们必须导入其他重要的库,这将有助于我们创建神经网络。
from sklearn.model_selection import train_test_split #to split data import numpy as np import pandas as pd import matplotlib.pyplot as plt import tensorflow as tf from tensorflow.keras.layers import Dense from tensorflow.keras.models import Sequential
在这里,我们从tensorflow中导入了2个主要的东西,分别是Dense和Sequential。 从tensorflow.keras.layers导入的Dense是紧密连接的一种层。 密集连接的层意味着先前层的所有节点都连接到当前层的所有节点。
Sequential是Keras的API,通常称为Sequential API,我们将使用它来构建神经网络。
为了更好地理解数据,我们可以将其转换为数据帧。 我们开始做吧。
X = pd.DataFrame(data = iris.data, columns = iris.feature_names) print(X.head())
X.head()
请注意,这里我们设置了column = iris.feature_names,其中feature_names是具有所有4个特征名称的键。
同样对于目标,
y = pd.DataFrame(data=iris.target, columns = [‘irisType’])
y.head()
要查看目标集合中的类数量,我们可以使用
y.irisType.value_counts()
这里我们可以看到我们有3个类,每个类都有标签0、1和2。
iris.target_names #它是iris词典的键值
这些是我们必须预测的类名称。
机器学习的数据预处理
目前,机器学习的第一步就是数据预处理。数据预处理的主要步骤是:
- 填入缺失值
- 将数据分割成为训练集以及验证集
- 对数据进行标准化处理
- 将类别性数据转换成为独热向量
缺失值
为了检查是否存在缺失值,我们可以用pandas.DataFrame.info()来进行检查工作。
X.info()
这样我们就可以看到我们(很幸运地)没有缺失值,并且所有特征都是float64格式的。
分割为训练集和测试集
为了将数据集分割为训练集和测试集,我们可以使用先前已经引入过的sklearn.model_selection中的train_test_split。
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.1)
其中test_size是一种声明,它说明我们希望整个数据集的10%被用来做为测试数据。
数据的标准化
一般情况下,当数据的偏差非常大的时候,我们会对数据进行标准化。为了查看偏差值,我们可以使用pandas.DataFrame中的var()函数来检查所有列的偏差值。
X_train.var(), X_test.var()
这样我们便可以看到,X_train和X_test的偏差值都非常低,因此无需对数据进行标准化。
将分类数据转换为一个独热向量
因为我们知道我们的输出数据是已经使用iris.target_name检查过的3个类之一,所以好消息是,当我们加载目标时,它们已经是0、1、2格式,其中0=1类,1=2类,依此类推。
这种表示方式的问题在于,我们的模型可能会赋予越高的数字更高的优先级,这可能会导致结果有偏差。 因此,为了解决这个问题,我们将使用单热点表示法。 你可以在这里了解更多关于一个热门载体的信息。 我们可以使用内置的KERS TO_CATEGRICAL,也可以使用skLearn中的OneHotEncoding。 我们将使用to_classical。
y_train = tf.keras.utils.to_categorical(y_train) y_test = tf.keras.utils.to_categorical(y_test)
我们将只检查前5行,以检查它是否已正确转换。
y_train[:5,:]
是的,我们已经把它转换成了独热的表达方式。
最后一件事
我们可以做的最后一件事是将我们的数据转换回Numpy数组,这样我们就可以使用一些额外的函数,这些函数将在稍后的模型中对我们有所帮助。 要做到这一点,我们可以使用
X_train = X_train.values X_test = X_test.values
让我们看看第一个训练示例的结果是什么。
X_train[0]
在这里,我们可以看到第一个训练示例中4个特征的值,它的形状是(4),
当我们在它们上使用to_Category时,我们的目标标签已经是数组格式。
机器学习模型
现在,我们终于准备好创建我们的模型并对其进行训练。 我们将从一个简单的模型开始,然后我们将转到复杂的模型结构,在那里我们将介绍Keras中的不同技巧和技术。
让我们对我们的基本模型进行编码
model1 = Sequential() #Sequential Object
首先,我们必须创建一个Sequential对象。 现在,要创建一个模型,我们所要做的就是根据我们的选择添加不同类型的层。 我们将制作一个10层的Dense层模型,这样我们就可以观察到过拟合,并在以后通过不同的正则化技术来减少它。
model1.add( Dense( 64, activation = 'relu', input_shape= X_train[0].shape)) model1.add( Dense (128, activation = 'relu') model1.add( Dense (128, activation = 'relu') model1.add( Dense (128, activation = 'relu') model1.add( Dense (128, activation = 'relu') model1.add( Dense (64, activation = 'relu') model1.add( Dense (64, activation = 'relu') model1.add( Dense (64, activation = 'relu') model1.add( Dense (64, activation = 'relu') model1.add( Dense (3, activation = 'softmax')
请注意,在我们的第一层中,我们使用了一个额外的参数INPUT_Shape。 此参数指定第一层的尺寸。 在这种情况下,我们不关心训练示例的数量。 相反,我们只关心功能的数量。 因此,我们传入任何训练示例的形状,在我们的示例中,它是(4,)在input_Shape内。
请注意,我们在输出层中使用了Softmax(激活函数),因为它是一个多类分类问题。 如果这是一个二进制分类问题,我们会使用Sigmoid激活函数。
我们可以传入任何我们想要的激活函数,如Sigmoid或linear或tanh,但实验证明relu在这类模型中表现最好。
现在,当我们定义了模型的形状后,下一步是指定它的损耗、优化器和度量。 我们在keras中使用Compile方法指定这些参数。
model1.compile(optimizer='adam', loss= 'categorical_crossentropy', metrics = ['acc'])
在这里,我们可以使用任何优化器,如随机梯度下降、RMSProp等,但我们将使用Adam。
我们在这里使用CATEGRICAL_CROSENTROPY是因为我们有一个多类分类问题,如果我们有一个二进制分类问题,我们将使用BINARY_CROSENTROPY。
衡量标准对于评估一个人的模型是很重要的。 我们可以根据不同的度量标准来评估我们的模型。 对于分类问题,最重要的衡量标准是准确度,它表明我们的预测有多准确。
我们模型的最后一步是将其匹配到训练数据和训练标签上。 让我们对它进行编码。
history = model1.fit(X_train, y_train, batch_size = 40, epochs=800, validation_split = 0.1
fit返回一个回调,其中包含我们训练的所有历史记录,我们可以使用它来执行不同的有用任务,如绘图等。
历史回调有一个名为history的属性,我们可以将其作为history.history进行访问,这是一个包含所有损失和指标历史的字典,即,在我们的示例中,它具有Loss、Acc、val_loses和val_acc的历史记录,并且我们可以将每个单独的历史记录作为 history.history.loss 或 history.history['val_acc'] 等进行访问。
我们有一个指定的epoch数为800,batch大小为40,验证拆分为0.1,这意味着我们现在有10%的验证数据,我们将使用这些数据来分析我们的训练。 使用800个epoch将过度拟合数据,这意味着它将在训练数据上执行得非常好,但在测试数据上则不会。
当模型进行训练时,我们可以看到我们在训练集和验证集上的损失和准确性。
在此,我们可以看到,训练集上的准确率是100%,验证集上的准确率则为67%,这对于这样一个模型来说已经很出色了。接下来就让我们画出图像。
plt.plot(history.history['acc']) plt.plot(history.history['val_acc']) plt.xlabel('Epochs') plt.ylabel('Acc') plt.legend(['Training', 'Validation'], loc='upper right')
我们可以很清楚地看到,训练集上的准确率要比验证集上高得多了。
类似地,我们用如下方法画出损失:
plt.plot(history.history['loss']) plt.plot(history.history['val_loss']) plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend(['Training', 'Validation'], loc='upper left')
在此,我们可以很清楚地看到,验证集上的损失比训练集上要大得多了,这是因为数据被过拟合了。
为了看看模型的表现是不是好,我们可以使用model.evaluate来查看。我们要将数据和标签放入评估函数中。
model1.evaluate(X_test, y_test)
这样,我们就可看到模型的准确率为88%,这对于一个过拟合的模型来说已经很好了。
正则化
让我们通过将正则化添加到我们的模型中来使它变得更好。 正则化将减少我们模型的过度拟合,并将改进我们的模型。
我们将在我们的模型中添加L2正则化。 单击 此处了解有关L2正则化的更多信息。 要在我们的模型中添加L2正则化,我们必须指定要添加正则化的层,并给出一个附加参数kernel_Regularizer,然后传递tf.keras.Regularizers.l2()。
我们还将在我们的模型中实现一些dropout,这将帮助我们更好地减少过拟合,从而获得更好的性能。 要阅读更多关于dropout背后的理论和动机,请参阅这篇文章。
让我们重新定义这个模型吧。
model2 = Sequential() model2.add(Dense(64, activation = 'relu', input_shape= X_train[0].shape)) model2.add( Dense(128, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add( Dense (128, activation = 'relu',kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add(tf.keras.layers.Dropout(0.5) model2.add( Dense (128, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add(Dense(128, activation = 'relu', kernel_regularizer = tf.keras.regularizers.l2(0.001) )) model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add(tf.keras.layers.Dropout(0.5) model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001) )) model2.add( Dense (3, activation = 'softmax', kernel_regularizer=tf.keras.regularizers.l2(0.001) ))
如果你仔细观察,我们所有的层和参数都是一样的,除了我们在每个dense层中增加了2个dropout层和正则化。
我们将保留所有其他东西(损失、优化器、epoch等)一样。
model2.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc']) history2 = model2.fit(X_train, y_train, epochs=800, validation_split=0.1, batch_size=40)
现在让我们评估一下模型。
你猜怎么着? 通过加入正则化和dropout层,我们的准确率从88%提高到94%。 如果我们增加了BN层,它将会进一步改善。
让我们把它画出来。
准确率
plt.plot(history2.history['acc']) plt.plot(history2.history['val_acc']) plt.title('Accuracy vs. epochs') plt.ylabel('Acc') plt.xlabel('Epoch') plt.legend(['Training', 'Validation'], loc='lower right') plt.show()
plt.plot(history2.history['loss']) plt.plot(history2.history['val_loss']) plt.title('Loss vs. epochs') plt.ylabel('Loss') plt.xlabel('Epoch') plt.legend(['Training', 'Validation'], loc='upper right') plt.show()
洞见