Python 机器学习秘籍第二版(六)
原文:
annas-archive.org/md5/1a114450f966ee5154c07d3ee2c9ce43译者:飞龙
第十四章:无监督表示学习
在本章中,我们将涵盖以下食谱:
-
使用降噪自编码器检测欺诈交易
-
使用 CBOW 或 skipgram 表示生成词嵌入
-
使用 PCA 和 t-SNE 可视化 MNIST 数据集
-
使用词向量进行 Twitter 情感分析
-
使用 scikit-learn 实现 LDA
-
使用 LDA 对文本文档进行分类
-
为 LDA 准备数据
技术要求
为了处理本章中的食谱,你需要以下文件(可在 GitHub 上找到):
-
CreditCardFraud.py -
creditcard.csv -
WordEmbeddings.py -
MnistTSNE.py -
TweetEmbeddings.py -
Tweets.csv -
LDA.py -
TopicModellingLDA.py -
PrepDataLDA.py
简介
在第四章《无监督学习聚类》中,我们已经讨论了无监督学习。我们说无监督学习是机器学习中的一个范例,我们在其中构建模型而不依赖于标记的训练数据。为什么回到这个话题?在这种情况下,我们将以无监督的方式讨论学习图像、视频和自然语言语料库等数据的表示问题。
使用降噪自编码器检测欺诈交易
在第四章《无监督学习聚类》中,我们处理了自编码器的主题。在自编码器重建手写数字图像食谱中,有一个神经网络,其目的是将其输入编码为小维度,并得到的结果能够重建输入本身。自编码器的目的不仅仅是执行一种输入的压缩或寻找身份函数的近似;还有一些技术可以让我们将模型(从减少维度的隐藏层开始)引导到给予某些数据属性更多的重要性。
准备工作
在这个食谱中,我们将以无监督模式训练一个自编码器来检测信用卡交易数据中的异常。为此,将使用信用卡欺诈检测数据集。这是一个包含标记为欺诈或真实的匿名信用卡交易的数据集。列出了 2013 年 9 月欧洲持卡人用信用卡进行的交易。该数据集中有 492 笔交易被标记为欺诈,占 284,807 笔交易中的 0.172%。该数据集高度不平衡,因为正类(欺诈)占所有交易的 0.172%。该数据集可在以下 URL 的 Kabble 上找到:www.kaggle.com/mlg-ulb/creditcardfraud。
如何做到这一点…
让我们看看如何使用降噪自编码器来检测欺诈交易:
- 创建一个新的 Python 文件,并导入以下包(完整的代码在已经提供给你的
CreditCardFraud.py文件中):
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from keras.models import Model
from keras.layers import Input, Dense
from keras import regularizers
- 为了使实验可重复,即在每次重复时提供相同的结果,有必要设置种子:
SetSeed = 1
- 如前所述,我们将使用已经提供给你的信用卡欺诈检测数据集(
creditcard.csv):
CreditCardData = pd.read_csv("creditcard.csv")
- 让我们计算两个类别(
fraud=1;normal=0)的出现次数:
CountClasses = pd.value_counts(CreditCardData['Class'], sort = True)
print(CountClasses)
返回以下结果:
0 284315
1 492
如预期,数据集高度不平衡——正类(frauds)有492个,而总共有284315个。
- 在可用的变量中,交易金额(
Amount)是最有趣的一个。让我们计算一些统计数据:
print(CreditCardData.Amount.describe())
返回以下结果:
count 284807.000000
mean 88.349619
std 250.120109
min 0.000000
25% 5.600000
50% 22.000000
75% 77.165000
max 25691.160000
- 如我们所见,这些值差异很大,标准差很高。建议对数据进行缩放。记住,在训练机器学习算法之前重新缩放数据是一个好的实践。通过缩放,消除了数据单位,使得你可以轻松地比较来自不同位置的数据。为此,我们将使用
sklearn的StandardScaler()函数。此函数移除了平均值并将值缩放到单位方差:
from sklearn.preprocessing import StandardScaler
Data = CreditCardData.drop(['Time'], axis=1)
Data['Amount'] = StandardScaler().fit_transform(Data['Amount'].values.reshape(-1, 1))
print(Data.Amount.describe())
返回以下结果:
count 2.848070e+05
mean 2.913952e-17
std 1.000002e+00
min -3.532294e-01
25% -3.308401e-01
50% -2.652715e-01
75% -4.471707e-02
max 1.023622e+02
因此,我们已经确认现在数据具有mean=0和单位方差。
- 现在,我们将起始数据分为两个集合:训练集(70%)和测试集(30%)。训练集将用于训练分类模型,测试集将用于测试模型性能:
XTrain, XTest = train_test_split(Data, test_size=0.3, random_state=SetSeed)
XTrain = XTrain[XTrain.Class == 0]
XTrain = XTrain.drop(['Class'], axis=1)
YTest = XTest['Class']
XTest = XTest.drop(['Class'], axis=1)
XTrain = XTrain.values
XTest = XTest.values
- 我们可以按照以下方式构建 Keras 模型:
InputDim = XTrain.shape[1]
InputModel = Input(shape=(InputDim,))
EncodedLayer = Dense(16, activation='relu')(InputModel)
DecodedLayer = Dense(InputDim, activation='sigmoid')(EncodedLayer)
AutoencoderModel = Model(InputModel, DecodedLayer)
AutoencoderModel.summary()
下图显示了模型架构:
- 因此,我们必须为训练配置模型。为此,我们将使用
compile()方法,如下所示:
NumEpoch = 100
BatchSize = 32
AutoencoderModel.compile(optimizer='adam',
loss='mean_squared_error',
metrics=['accuracy'])
- 到这一点,我们可以训练模型:
history = AutoencoderModel.fit(XTrain, XTrain,
epochs=NumEpoch,
batch_size=BatchSize,
shuffle=True,
validation_data=(XTest, XTest),
verbose=1,
).history
- 现在,我们可以绘制损失历史记录来评估模型收敛性:
plt.plot(history['loss'])
plt.plot(history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right');
- 到这一点,我们使用模型来重建交易的预测结果:
PredData = AutoencoderModel.predict(XTest)
mse = np.mean(np.power(XTest - PredData, 2), axis=1)
ErrorCreditCardData = pd.DataFrame({'Error': mse,
'TrueClass': YTest})
ErrorCreditCardData.describe()
为了评估预测的质量,我们使用了均方误差(MSE)损失函数。MSE 衡量误差平方的平均值——即估计值与实际估计值之间的平均平方差。MSE 是估计质量的一个度量——它总是非负的,并且值接近零。因此,我们计算了一些与误差和真实值相关的统计数据。以下结果如下:
- 现在,我们可以比较分类结果与实际值。最好的方法是使用混淆矩阵。在混淆矩阵中,我们比较我们的结果与真实数据。混淆矩阵的好处是它确定了分类错误的性质以及它们的数量。在这个矩阵中,对角线单元格显示了正确分类的案例数量;所有其他单元格显示了错误分类的案例。为了计算混淆矩阵,我们可以使用包含在
sklearn.metrics包中的confusion_matrix()函数,如下所示:
from sklearn.metrics import confusion_matrix
threshold = 3.
YPred = [1 if e > threshold else 0 for e in ErrorCreditCardData.Error.values]
ConfMatrix = confusion_matrix(ErrorCreditCardData.TrueClass, YPred)
print(ConfMatrix)
返回以下混淆矩阵:
[[83641 1667]
[ 28 107]]
- 最后,我们将计算模型的准确度:
from sklearn.metrics import accuracy_score
print(accuracy_score(ErrorCreditCardData.TrueClass, YPred))
以下为获得的准确度:
0.9801622134054282
结果看起来很棒,但不幸的是,输入数据集高度不平衡。如果我们只评估欺诈交易的准确度,这些数据将显著减少。
它是如何工作的...
可用的自动编码器类型不同:
-
香草自动编码器:这是最简单的形式,其特征是一个三层网络,即只有一个隐藏层的神经网络。输入和输出是相同的。
-
多层自动编码器:如果只有一个隐藏层不够,我们可以沿着深度维度扩展自动编码器。例如,使用三个隐藏层以获得更好的泛化能力,但我们也必须使用中间层构建对称网络。
-
卷积自动编码器:使用三维向量而不是一维向量。输入图像被采样以获得潜在表示,即降维,从而迫使自动编码器从图像的压缩版本中学习。
-
正则化自动编码器:正则化自动编码器不是通过维持浅层的编码器和解码器架构以及强制减少来限制模型的能力,而是使用损失函数来鼓励模型假设一些超出简单复制输入到输出的能力的属性。
更多内容...
实际上,我们发现有两种不同类型:
-
稀疏自动编码器:这通常用于分类。通过训练自动编码器,中间层的隐藏单元被激活得太频繁。为了避免这种情况,我们需要通过将其限制为训练数据的一部分来降低它们的激活率。这种约束称为稀疏性约束,因为每个单元只被预定义类型的一种输入激活。
-
去噪自动编码器:我们不是对损失函数添加惩罚,而是让对象发生变化,向输入图像添加噪声,并让自动编码器自主地学习去除它。这意味着网络将只提取最相关的信息,并从数据的一个鲁棒表示中学习。
参考内容
-
参考 Keras 库的官方文档:
keras.io/ -
参考来自斯坦福大学的自动编码器教程:
ufldl.stanford.edu/tutorial/unsupervised/Autoencoders/
使用 CBOW 和 skipgram 表示生成词嵌入
在第七章“分析文本数据”中,我们已经处理了这个主题。在使用 gensim 的 Word2Vec配方中,我们使用了gensim库来构建 word2vec 模型。现在,我们将深入探讨这个主题。词嵌入允许计算机从未知语料库开始记住单词的语义和句法信息,并构建一个向量空间,其中单词的向量如果它们在相同的语言环境中出现,即如果它们被认为是语义上更相似的话,则彼此更接近。Word2vec是一组模板,用于生成词嵌入。
准备工作
在这个配方中,我们将使用gensim库生成词嵌入。我们还将分析两种实现此目的的技术:CBOW 和 skip gram 表示。
如何做...
让我们看看如何使用 CBOW 和 skip gram 表示来生成词嵌入:
- 创建一个新的 Python 文件,并导入以下包(完整代码在已提供的
WordEmbeddings.py文件中):
import gensim
- 让我们定义训练数据:
sentences = [['my', 'first', 'book', 'with', 'Packt', 'is', 'on','Matlab'],
['my', 'second', 'book', 'with', 'Packt', 'is', 'on','R'],
['my', 'third', 'book', 'with', 'Packt', 'is', 'on','Python'],
['one', 'more', 'book'],
['is', 'on', 'Python', 'too']]
- 现在,我们可以训练第一个模型:
Model1 = gensim.models.Word2Vec(sentences, min_count=1, sg=0)
使用了三个参数:
-
sentences: 训练数据 -
min_count=1: 训练模型时考虑的单词的最小计数 -
sg=0: 训练算法,CBOW(0)或 skip gram(1)
- 让我们打印出模型的摘要:
print(Model1)
返回以下结果:
Word2Vec(vocab=15, size=100, alpha=0.025)
- 让我们列出并打印词汇表的摘要:
wordsM1 = list(Model1.wv.vocab)
print(wordsM1)
返回以下结果:
['my', 'first', 'book', 'with', 'Packt', 'is', 'on', 'Matlab', 'second', 'R', 'third', 'Python', 'one', 'more', 'too']
- 最后,我们将访问一个单词的向量(
book):
print(Model1.wv['book'])
返回以下结果:
- 要使用
skipgram算法,我们需要执行类似的步骤,但我们将参数sg设置为 1,如下所示:
Model2 = gensim.models.Word2Vec(sentences, min_count=1, sg=1)
它是如何工作的...
Word2vec 使用连续词袋(CBOW)和 skip gram 进行词嵌入。在 CBOW 算法中,模型从周围上下文词的窗口中预测当前词。上下文词的顺序不影响预测。在 skip gram 算法中,模型使用当前词来预测周围窗口的上下文词。
还有更多…
根据作者的说法,CBOW 和 skip-gram 都是好的,但对于不常见的单词来说,skip-gram 做得更好。
参见
-
参考官方的
gensim库文档:radimrehurek.com/gensim/ -
参考由 Tomas Mikolov 等人撰写的《在向量空间中高效估计词表示》(
arxiv.org/abs/1301.3781)
使用 PCA 和 t-SNE 可视化 MNIST 数据集
在重要维度的数据集中,数据先前被转换成一系列表示函数的简化序列。将输入数据转换成一组功能的过程称为特征提取。这是因为特征提取是从一系列初始测量数据开始的,并产生导出的值,这些值可以保留原始数据集中的信息,但释放了冗余数据。
这样,后续的学习和泛化阶段将得到简化,在某些情况下,这会导致更好的解释。这是一个从原始特征中提取新特征的过程,从而降低了特征测量的成本,提高了分类器的效率。如果特征选择得当,假设特征集将以减少的表示形式运行所需的任务,而不是全尺寸的输入。
准备工作
在这个菜谱中,我们将使用主成分分析(PCA)和t-分布随机邻域嵌入方法(t-SNE)来执行特征提取过程。这样,我们将能够可视化一个非常大的数据集(如 MNIST)的不同元素是如何组合在一起的。
如何做到这一点...
让我们看看如何使用 PCA 和 t-SNE 可视化 MNIST 数据集:
- 创建一个新的 Python 文件,并导入以下包(完整代码在已提供的
MnistTSNE.py文件中):
import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
- 要导入
mnist数据集,必须使用以下代码:
(XTrain, YTrain), (XTest, YTest) = mnist.load_data()
返回以下元组:
-
XTrain,XTest:一个形状为(num_samples,28,28)的灰度图像数据的uint8数组 -
YTrain,YTest:一个形状为(num_samples)的数字标签(0-9 范围内的整数)的uint8数组
- 为了降低维度,我们将 28 x 28 的图像展平成大小为 784 的向量:
XTrain = XTrain.reshape((len(XTrain), np.prod(XTrain.shape[1:])))
XTest = XTest.reshape((len(XTest), np.prod(XTest.shape[1:])))
- 我们只从这个大数据集中提取一部分数据以获得更好的可视化(仅 1,000 条记录):
from sklearn.utils import shuffle
XTrain, YTrain = shuffle(XTrain, YTrain)
XTrain, YTrain = XTrain[:1000], YTrain[:1000]
- 让我们进行
pca分析:
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
XPCATransformed = pca.fit_transform(XTrain)
- 我们显示新计划中可用的数据:
fig, plot = plt.subplots()
fig.set_size_inches(70, 50)
plt.prism()
plot.scatter(XPCATransformed[:, 0], XPCATransformed[:, 1], c=YTrain)
plot.legend()
plot.set_xticks(())
plot.set_yticks(())
plt.tight_layout()
返回以下结果:
- 在这一点上,我们将使用 t-SNE 方法重复该过程:
from sklearn.manifold import TSNE
TSNEModel = TSNE(n_components=2)
XTSNETransformed = TSNEModel.fit_transform(XTrain)
- 我们显示新计划中可用的数据:
fig, plot = plt.subplots()
fig.set_size_inches(70, 50)
plt.prism()
plot.scatter(XTSNETransformed[:, 0], XTSNETransformed[:, 1], c=YTrain)
plot.set_xticks(())
plot.set_yticks(())
plt.tight_layout()
plt.show()
返回以下结果:
比较获得的两个结果,很明显,第二种方法使我们能够更详细地识别代表不同数字的组。
它是如何工作的...
PCA 创建了一组新的变量,即主成分。每个主成分是原始变量的线性组合。所有主成分彼此正交,因此没有冗余信息。整体而言,主成分构成了数据空间的正交基。PCA 的目标是使用最少的几个主成分来解释最大的方差。PCA 是一种多维缩放技术。它将变量转换到一个低维空间,保留变量最多的细节。因此,主成分是原始变量经过线性变换后的组合。
t-SNE 是由 Geoffrey Hinton 和 Laurens van der Maaten 开发的一种降维算法,在许多研究领域被广泛用作自动学习工具。它是一种非线性降维技术,特别适合将高维数据集嵌入到二维或三维空间中,通过散点图进行可视化。该算法对点进行建模,使得原始空间中邻近的对象在降维后彼此靠近,而远离的对象则相隔较远,试图保留局部结构。
更多内容...
t-SNE 算法分为两个主要阶段。在第一阶段,构建一个概率分布,使得原始高维空间中的每对点,如果两点相似,则赋予高概率值,如果不相似,则赋予低概率值。然后,在小型空间中定义第二个类似的概率分布。算法随后通过下降梯度,最小化两个分布的 Kullback-Leibler 散度,重新组织小型空间中的点。
参见
-
参考官方文档中的
sklearn.decomposition.PCA函数:scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html -
sklearn.manifold.TSNE函数的官方文档:scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.htm
使用词嵌入进行 Twitter 情感分析
在 第七章,分析文本数据 中,我们已经处理了情感分析。在 分析句子情感 的配方中,我们使用 movie_reviews 语料库中的数据,通过朴素贝叶斯分类器分析了句子的情感。当时,我们说情感分析是 NLP 最受欢迎的应用之一。情感分析 指的是确定给定文本片段是正面还是负面的过程。在某些变体中,我们将 "中性" 作为第三个选项。
准备工作
在这个菜谱中,我们将使用词嵌入方法来分析一些美国航空公司的客户 Twitter 帖子的情感。Twitter 数据是根据一些贡献者的意见进行分类的。他们首先被要求对正面、负面和中性的帖子进行分类,然后对负面帖子进行分类。数据集可在以下链接获取:www.kaggle.com/crowdflower/twitter-airline-sentiment。
如何做到这一点…
让我们看看如何使用词嵌入进行 Twitter 情感分析:
- 创建一个新的 Python 文件,并导入以下包(完整的代码在您已提供的
TweetEmbeddings.py文件中):
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical
from sklearn.preprocessing import LabelEncoder
from keras import models
from keras import layers
- 要导入
Tweets数据集(您已提供的Tweets.csv文件),必须使用以下代码:
TweetData = pd.read_csv('Tweets.csv')
TweetData = TweetData.reindex(np.random.permutation(TweetData.index))
TweetData = TweetData[['text', 'airline_sentiment']]
只提取了两列:
-
text:Twitter 帖子 -
airline_sentiment:正面、中性或负面的分类
- 现在,我们将起始数据分为两个集合:训练集(70%)和测试集(30%)。训练集将用于训练分类模型,测试集将用于测试模型性能:
XTrain, XTest, YTrain, YTest = train_test_split(TweetData.text, TweetData.airline_sentiment, test_size=0.3, random_state=11)
- 现在,我们将单词转换为数字:
TkData = Tokenizer(num_words=1000,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{"}~\t\n',lower=True, split=" ")
TkData.fit_on_texts(XTrain)
XTrainSeq = TkData.texts_to_sequences(XTrain)
XTestSeq = TkData.texts_to_sequences(XTest)
要做到这一点并对XTrain数据集进行分词,使用了fit_on_texts和texts_to_sequences方法。
- 为了将输入数据转换为与 Keras 兼容的格式,将使用
pad_sequences模型。该方法将序列(标量列表)转换为二维 NumPy 数组,如下所示:
XTrainSeqTrunc = pad_sequences(XTrainSeq, maxlen=24)
XTestSeqTrunc = pad_sequences(XTestSeq, maxlen=24)
- 因此,我们将目标类别转换为数字:
LabelEnc = LabelEncoder()
YTrainLabelEnc = LabelEnc.fit_transform(YTrain)
YTestLabelEnc = LabelEnc.transform(YTest)
YTrainLabelEncCat = to_categorical(YTrainLabelEnc)
YTestLabelEncCat = to_categorical(YTestLabelEnc)
- 现在,我们将构建 Keras 模型:
EmbModel = models.Sequential()
EmbModel.add(layers.Embedding(1000, 8, input_length=24))
EmbModel.add(layers.Flatten())
EmbModel.add(layers.Dense(3, activation='softmax'))
嵌入层接受一个形状为(batch_size,sequence_length)的二维张量作为输入,其中每个条目都是一个整数序列。返回一个形状为(batch_size,sequence_length,output_dim)的三维张量。
- 现在,我们将编译和拟合创建的模型:
EmbModel.compile(optimizer='rmsprop'
, loss='categorical_crossentropy'
, metrics=['accuracy'])
EmbHistory = EmbModel.fit(XTrainSeqTrunc
, YTrainLabelEncCat
, epochs=100
, batch_size=512
, validation_data=(XTestSeqTrunc, YTestLabelEncCat)
, verbose=1)
- 为了评估模型性能,让我们打印准确率:
print('Train Accuracy: ', EmbHistory.history['acc'][-1])
print('Validation Accuracy: ', EmbHistory.history['val_acc'][-1])
返回以下结果:
Train Accuracy: 0.9295472287275566
Validation Accuracy: 0.7625227688874486
- 最后,我们将绘制模型历史:
plt.plot(EmbHistory.history['acc'])
plt.plot(EmbHistory.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'Validation'], loc='upper left')
plt.show()
返回以下图表:
分析验证损失的进展,我们发现模型过拟合了。为了处理过拟合,正如我们在第一章中学习到的Building a ridge regressor菜谱中,The Realm of Supervised Learning,我们需要使用正则化方法。
它是如何工作的...
术语情感分析指的是使用自然语言处理技术、文本分析和计算语言学来识别和提取书面或口头文本来源中的主观信息。情感分析可以通过不同的方法来解决。最常用的方法可以分为四个宏观类别(Collomb A, Costea C, Joyeux D, Hasan O, 和 Brunie L 的 2014 年论文《A Study and Comparison of Sentiment Analysis Methods for Reputation Evaluation》):
-
基于词典的方法:这些方法检测情感关键词,并为可能代表特定情感的任意单词分配亲和力。
-
基于规则的方法:这些方法根据情感词(如快乐、悲伤和无聊)的存在使用情感类别对文本进行分类。
-
统计方法:在这里,我们试图识别情感的所有者,即主体是谁,以及目标,即情感所感受到的对象。为了在上下文中衡量观点并找到被评判的特征,我们检查文本中单词之间的语法关系。这是通过对文本进行彻底扫描获得的。
-
机器学习方法:这些方法使用不同的学习算法通过使数据集分类(监督方法)来确定情感。学习过程不是即时的;事实上,必须构建将极性关联到不同类型评论的模型,以及必要时用于分析目的的主题。
还有更多…
正则化方法涉及修改性能函数,通常选择为训练集上回归误差平方和。当有大量变量可用时,线性模型的平方估计通常具有较低的偏差,但相对于变量较少的模型具有较高的方差。在这些条件下,存在过拟合问题。为了通过允许更大的偏差但较小的方差来提高预测精度,我们可以使用变量选择方法和降维,但这些方法在第一种情况下可能因计算负担而不吸引人,或者在另一种情况下可能难以解释。
相关内容
-
参考 Keras 库的官方文档:
keras.io/ -
参考斯坦福大学的情感分析(
web.stanford.edu/class/cs124/lec/sentiment.pdf)
使用 scikit-learn 实现 LDA
潜在狄利克雷分配(LDA)是一种生成模型,用于自然语言研究,它允许您从一组源文档中提取论点,并对文档各个部分的相似性提供逻辑解释。每个文档被视为一组单词,当它们结合在一起时,形成一个或多个潜在主题的子集。每个主题由特定术语分布的特征所表征。
准备工作
在这个菜谱中,我们将使用sklearn.decomposition.LatentDirichletAllocation函数生成一个标记计数特征矩阵,类似于CountVectorizer函数(在第七章的构建词袋模型菜谱中已使用)在文本上产生的结果。
如何操作…
让我们看看如何使用 scikit-learn 实现 LDA:
- 创建一个新的 Python 文件,并导入以下包(完整代码在已提供的
LDA.py文件中):
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.datasets import make_multilabel_classification
- 为了生成输入数据,我们将使用
sklearn.datasets.make_multilabel_classification函数。此函数生成一个随机的多标签分类问题,如下所示:
X, Y = make_multilabel_classification(n_samples=100, n_features=20, n_classes=5, n_labels=2, random_state=1)
返回以下数据:
-
X:生成的样本,是一个形状为[n_samples, n_features]的数组 -
Y:标签集,是一个形状为[n_samples, n_classes]的数组或稀疏 CSR 矩阵
在我们的情况下,Y变量将不会为我们服务,因为我们将使用一种无监督方法,正如我们所知,这种方法不需要对数据标签的先验知识。
- 现在,我们可以构建
LatentDirichletAllocation()模型(使用在线变分贝叶斯算法):
LDAModel = LatentDirichletAllocation(n_components=5, random_state=1)
只传递了两个参数:
-
n_components=5:这是主题的数量,5,因为我们使用了一个基于五个组构建的输入数据集。 -
random_state=1:这是随机数生成器使用的种子。
- 现在,我们将使用变分贝叶斯方法对数据
X进行模型训练:
LDAModel.fit(X)
- 最后,我们将获取
X数据集最后 10 个样本的主题:
print(LDAModel.transform(X[-10:]))
返回以下结果:
对于提供的每个输入示例,返回一个包含五个值的序列,表示该主题属于该组的概率。显然,最接近 1 的值代表最佳概率。
它是如何工作的...
LDA 算法的生成过程基于对文本中包含的数据的分析。将词组合视为随机变量。LDA 算法可以以下方式进行执行:
-
每个主题都与一个词分布相关联
-
每个文档都位于一个主题分布中
-
对于文档中的每个单词,验证其归属到文档主题和主题的词分布
更多内容...
根据推理类型,LDA 算法允许我们在时间和空间复杂度方面达到一定水平的效果和成本(效率)。LDA 模型首次于 2003 年由 David Blei、Andrew Ng 和 Michael Jordan 在发表的一篇论文中提出。
参见
-
请参考
sklearn.decomposition.LatentDirichletAllocation函数的官方文档:scikit-learn.org/stable/modules/generated/sklearn.decomposition.LatentDirichletAllocation.html -
请参考潜在狄利克雷分配(由 David Blei、Andrew Ng 和 Michael Jordan 所著):
www.jmlr.org/papers/volume3/blei03a/blei03a.pdf -
请参考第七章,分析文本数据
使用 LDA 对文本文档进行分类
LDA 是一种自然语言分析模型,它通过分析文档中术语分布与特定主题(主题)或实体分布的相似性,来理解文本的语义意义。最近,LDA 在语义 SEO 领域也因其可能是谷歌搜索引擎的排名因素而声名鹊起。
准备工作
在这个配方中,我们将使用sklearn.decomposition.LatentDirichletAllocation函数进行主题建模分析。
如何操作…
让我们看看如何使用 LDA 对文本文档进行分类:
- 创建一个新的 Python 文件,并导入以下包(完整的代码在您已提供的
TopicModellingLDA.py文件中):
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.datasets import fetch_20newsgroups
- 为了导入数据,我们将使用
sklearn库中的fetch_20newsgroups数据集:
NGData = fetch_20newsgroups(shuffle=True, random_state=7,
remove=('headers', 'footers', 'quotes'))
这是一个大约有 20,000 篇新闻组文档的集合,分为 20 个不同的新闻组。该数据集特别适用于处理文本分类问题。
- 现在,我们将打印可用的新闻组名称:
print(list(NGData.target_names))
以下结果返回:
['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']
- 数据中有 11,314 个样本。我们将只提取 2,000 个:
NGData = NGData.data[:2000]
- 现在,我们将提取一个文档词频矩阵。这基本上是一个计数文档中每个单词出现次数的矩阵。因此,我们将定义对象,并提取文档词频矩阵:
NGDataVect = CountVectorizer(max_df=0.93, min_df=2,
max_features=1000,
stop_words='english')
NGDataVectModel = NGDataVect.fit_transform(NGData)
- 现在,我们可以构建 LDA 模型(使用在线变分贝叶斯算法):
LDAModel = LatentDirichletAllocation(n_components=10, max_iter=5,
learning_method='online',
learning_offset=50.,
random_state=0)
- 我们将使用变分贝叶斯方法对
NGDataVectModel数据进行模型训练:
LDAModel.fit(NGDataVectModel)
- 最后,我们将打印提取的主题:
NGDataVectModelFeatureNames = NGDataVect.get_feature_names()
for topic_idx, topic in enumerate(LDAModel.components_):
message = "Topic #%d: " % topic_idx
message += " ".join([NGDataVectModelFeatureNames[i]
for i in topic.argsort()[:-20 - 1:-1]])
print(message)
以下结果返回:
工作原理…
主题建模指的是在文本数据中识别隐藏模式的过程。目标是揭示文档集合中的一些隐藏主题结构。这将帮助我们更好地组织文档,以便我们可以用于分析。这是 NLP 研究的一个活跃领域。
LDA 分析自动允许通过与参考知识库(KB)的共现关联,回溯到短语的议题,而无需解释句子的含义。
更多内容…
在这里,德·芬蒂定理表明,任何可变随机变量的集合都可以表示为分布的混合,因此如果您想要有可交换的单词和文档表示,就必须考虑同时捕捉两者可交换性的混合。LDA 模型思想方法的基础就是这种方法的根源。
参考以下内容
-
参考官方文档的
sklearn.decomposition.LatentDirichletAllocation函数:scikit-learn.org/stable/modules/generated/sklearn.decomposition.LatentDirichletAllocation.html -
请参阅第七章,分析文本数据
-
参考牛津大学的交换性和 de Finetti 定理(
www.stats.ox.ac.uk/~steffen/teaching/grad/definetti.pdf)
准备 LDA 数据
在之前的配方中,“使用 LDA 对文本文档进行分类”,我们看到了如何使用 LDA 算法进行主题建模。我们了解到,在构建算法之前,数据集必须经过适当的处理,以便将数据准备成与 LDA 模型提供的输入格式兼容的形式。在这个配方中,我们将详细分析这些程序。
准备工作
在这个配方中,我们将分析将特定数据集中包含的数据进行转换所需的程序。然后,这些数据将被用作基于 LDA 方法的算法的输入。
如何做...
让我们看看如何为 LDA 准备数据:
- 创建一个新的 Python 文件,并导入以下包(完整的代码在已经提供给你的
PrepDataLDA.py文件中):
from nltk.tokenize import RegexpTokenizer
from stop_words import get_stop_words
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models
- 我们定义了一系列我们想要从中提取主题的句子:
Doc1 = "Some doctors say that pizza is good for your health."
Doc2 = "The pizza is good to eat, my sister likes to eat a good pizza, but not to my brother."
Doc3 = "Doctors suggest that walking can cause a decrease in blood pressure."
Doc4 = "My brother likes to walk, but my sister don't like to walk."
Doc5 = "When my sister is forced to walk for a long time she feels an increase in blood pressure."
Doc6 = "When my brother eats pizza, he has health problems."
在我们刚刚定义的句子中,有一些主题以不同的含义重复出现。很难在这些主题之间建立联系。
- 我们将这些句子插入到一个列表中:
DocList = [Doc1, Doc2, Doc3, Doc4, Doc5, Doc6]
- 我们设置了在转换过程中将使用的元素:
Tokenizer = RegexpTokenizer(r'\w+')
EnStop = get_stop_words('en')
PStemmer = PorterStemmer()
Texts = []
- 要对所有短语进行转换,需要设置一个循环,只需遍历列表:
for i in DocList:
- 现在,我们可以开始准备数据。分词是将文本分割成一组有意义的片段的过程。这些片段被称为标记。例如,我们可以将一大块文本分割成单词,或者我们可以将其分割成句子。让我们从句子分词开始:
raw = i.lower()
Tokens = Tokenizer.tokenize(raw)
- 让我们继续到移除无意义词语。在典型的英语句子中,有些词对于主题模型的建设并不具有显著意义。例如,连词和冠词并不能帮助识别主题。这些术语被称为停用词,必须从我们的标记列表中移除。这些术语(停用词)根据我们操作的环境而变化。让我们移除停用词:
StoppedTokens = [i for i in Tokens if not i in EnStop]
- 数据准备的最后阶段是词干提取。词干提取的目标是将这些不同形式归入一个共同的基形式。这使用一种启发式过程来截断词尾以提取基形式。让我们进行词干提取:
StemmedTokens = [PStemmer.stem(i) for i in StoppedTokens]
- 我们只需将获得的元素添加到文本列表中:
Texts.append(StemmedTokens)
- 到目前为止,我们必须将我们的标记列表转换成字典:
Dictionary = corpora.Dictionary(Texts)
- 因此,让我们使用标记文档构建一个文档-词矩阵:
CorpusMat = [Dictionary.doc2bow(text) for text in Texts]
- 最后,我们构建了一个 LDA 模型并打印出提取的主题:
LDAModel = models.ldamodel.LdaModel(CorpusMat, num_topics=3, id2word = Dictionary, passes=20)
print(LDAModel.print_topics(num_topics=3, num_words=3))
返回以下结果:
[(0, '0.079*"walk" + 0.079*"blood" + 0.079*"pressur"'),
(1, '0.120*"like" + 0.119*"eat" + 0.119*"brother"'),
(2, '0.101*"doctor" + 0.099*"health" + 0.070*"pizza"')]
它是如何工作的...
数据准备对于创建主题模型至关重要。数据准备要经过以下程序:
-
分词:将文档转换为它的原子元素
-
停用词:移除无意义的词
-
词干提取:意义等效词的融合
还有更多...
数据准备取决于我们处理文本的类型。在某些情况下,在将数据提交给 LDA 算法之前,执行进一步操作是必要的。例如,可以包括去除标点符号,以及去除特殊字符。
参考以下内容
-
参考斯坦福大学 NLP 小组的分词:
nlp.stanford.edu/IR-book/html/htmledition/tokenization-1.html -
参考斯坦福大学的词干提取和词形还原:
nlp.stanford.edu/IR-book/html/htmledition/stemming-and-lemmatization-1.html -
参考斯坦福大学的去除常见术语:停用词:
nlp.stanford.edu/IR-book/html/htmledition/dropping-common-terms-stop-words-1.html
第十五章:自动化机器学习和迁移学习
在本章中,我们将介绍以下配方:
-
使用 Auto-WEKA
-
使用 AutoML 和 TPOT 生成机器学习管道
-
使用 Auto-Keras
-
使用 auto-sklearn
-
使用 MLBox 进行选择和泄漏检测
-
带有迁移学习的卷积神经网络
-
迁移学习 – 使用 ResNet-50 预训练图像分类器
-
迁移学习 – 使用 VGG16 模型进行特征提取
-
使用重新训练的 GloVe 嵌入进行迁移学习
技术要求
为了处理本章中的配方,您需要以下文件(可在 GitHub 上找到):
-
TPOTIrisClassifier.py -
AKClassifier.py -
MLBoxRegressor.py -
ASKLClassifier.py -
ImageTransferLearning.py -
PretrainedImageClassifier.py -
ExtractFeatures.py -
PTGloveEMB.py
简介
自动化机器学习(AutoML)指的是那些能够自动化将机器学习应用于现实世界问题端到端过程的应用。通常,科学分析师必须在将数据提交给机器学习算法之前,通过一系列的初步程序来处理数据。在前几章中,您看到了通过这些算法进行适当数据分析的必要步骤。您看到了如何通过使用几个库来构建基于深度神经网络的模型是多么简单。在某些情况下,这些技能超出了分析师所拥有的,他们必须寻求行业专家的支持来解决该问题。
AutoML 的诞生源于创建一个能够自动化整个机器学习过程的应用的需求,以便用户可以利用这些服务。通常,机器学习专家必须执行以下任务:
-
数据准备
-
选择特征
-
选择合适的模型类别
-
选择和优化模型超参数
-
后处理机器学习模型
-
分析获得的结果
AutoML 自动化所有这些操作。它提供了产生更简单、创建更快且通常优于手工设计的解决方案的优势。存在许多 AutoML 框架;在接下来的几节中,我们将探讨其中的一些。
使用 Auto-WEKA
Weka 是一个完全用 Java 编写的软件环境。Weka,即Waikato 知识分析环境的缩写,是在新西兰的 Waikato 大学开发的机器学习软件。它是开源的,并按照 GNU 通用公共许可证进行分发。使用它,可以基于机器学习构建许多模型。
然而,每个算法都有自己的超参数,这些参数可能会极大地改变它们的性能。研究人员的任务是找到这些参数的正确组合,以最大化模型的性能。Auto-WEKA 自动解决了选择学习算法及其超参数设置的问题。
准备就绪
在这个菜谱中,你将学习如何在三个主要步骤中使用 Auto-WEKA。要使用这个库,必须先安装它。有关系统要求和安装程序的详细信息,请参阅www.cs.ubc.ca/labs/beta/Projects/autoweka/manual.pdf。
如何操作...
让我们看看如何使用 Auto-WEKA,如下所示:
-
构建实验定义并实例化:在这个步骤中,你指定要使用哪个数据集以及要执行哪种类型的超参数搜索。然后,实验被完全实例化,以便 Auto-WEKA 可以识别要使用的分类器。在这个阶段,Auto-WEKA 将所有路径转换为绝对路径。
-
实验执行:Auto-WEKA 通过使用多个随机种子运行相同的实验来利用多个核心;唯一的要求是所有实验都有一个相似的文件系统。
-
分析阶段:当 Auto-WEKA 使用基于模型的优化方法时,它会生成一个超参数轨迹,这些超参数是由优化方法在特定时间识别为最佳的超参数。分析的最简单形式是检查在所有种子中找到的最佳超参数,并使用训练好的模型对新数据集进行预测。
它是如何工作的...
为了选择学习算法并设置其超参数,Auto-WEKA 使用一种完全自动化的方法,利用贝叶斯优化方面的最新创新。
更多内容...
Auto-WEKA 是第一个使用贝叶斯优化来自动实例化高度参数化机器学习框架的库。后来,AutoML 也被其他库所应用。
参考以下内容
-
参考官方 Auto-WEKA 网站:
www.cs.ubc.ca/labs/beta/Projects/autoweka/ -
参考以下文档:Auto-WEKA 2.0:在 WEKA 中进行自动模型选择和超参数优化:
www.cs.ubc.ca/labs/beta/Projects/autoweka/papers/16-599.pdf -
参考以下文档:Auto-WEKA:分类算法的联合选择和超参数优化:
www.cs.ubc.ca/labs/beta/Projects/autoweka/papers/autoweka.pdf
使用 AutoML 和 TPOT 生成机器学习管道
TPOT是一个 Python 自动化机器学习工具,通过使用遗传编程优化机器学习管道。在人工智能中,遗传算法是进化算法类的一部分。进化算法的一个特点是使用从自然进化中借鉴的技术来寻找问题的解决方案。寻找问题解决方案的过程被委托给一个迭代过程,该过程通过选择和重组越来越精细的解决方案,直到达到最优性标准。在遗传算法中,通过进化压力将解决方案种群推向一个既定目标。
准备工作
在本教程中,你将学习如何使用 TPOT 构建最佳性能模型,从iris数据集对鸢尾花物种(setosa、virginica 和 versicolor)进行分类。要使用此库,必须安装它。有关系统要求和安装过程的信息,请参阅epistasislab.github.io/tpot/installing/。
如何做到这一点...
让我们看看如何使用 AutoML 通过 TPOT 生成机器学习管道:
- 创建一个新的 Python 文件并导入以下包(完整代码已在提供的
TPOTIrisClassifier.py文件中给出):
from tpot import TPOTClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np
- 让我们按照以下方式导入鸢尾花数据集:
IrisData = load_iris()
- 让我们按照以下方式分割数据集:
XTrain, XTest, YTrain, YTest = train_test_split(IrisData.data.astype(np.float64),
IrisData.target.astype(np.float64), train_size=0.70, test_size=0.30)
- 现在,我们可以构建分类器:
TpotCL = TPOTClassifier(generations=5, population_size=50, verbosity=2)
- 然后,我们可以训练模型:
TpotCL.fit(XTrain, YTrain)
- 然后,我们将使用未见过的数据(
XTest)来评估模型性能:
print(TpotCL.score(XTest, YTest))
- 最后,我们将导出模型管道:
TpotCL.export('TPOTIrisPipeline.py')
如果你运行此代码,将返回一个大约 97%测试准确率的管道。
它是如何工作的...
TPOT 通过结合灵活的管道表达式树表示和随机搜索算法(如遗传编程)来自动化机器学习管道的构建。在本教程中,你学习了如何使用 TPOT 搜索最佳管道来从鸢尾花数据集对鸢尾花物种进行分类。
还有更多...
TPOT 是在scikit-learn的基础上构建的,因此,鉴于前几章广泛使用了scikit-learn库,生成的所有代码对我们来说都非常熟悉。TPOT 是一个处于积极开发中的平台,因此它将不断更新。
参见
-
TPOT 工具的官方文档:
epistasislab.github.io/tpot/ -
通过基于树的管道优化自动化生物医学数据科学,作者:Randal S. Olson, Ryan J. Urbanowicz, Peter C. Andrews, Nicole A. Lavender, La Creis Kidd, 和 Jason H. Moore (2016)
使用 Auto-Keras
Auto-Keras 是一个开源的 AutoML 软件库,旨在提供轻松访问深度学习模型。Auto-Keras 具有许多功能,允许您自动设置深度学习模型的架构和参数。其易用性、简单安装和大量示例使其成为一个非常受欢迎的框架。Auto-Keras 由德克萨斯 A&M 大学的 DATA 实验室和社区贡献者开发。
准备工作
在本食谱中,您将学习如何使用 Auto-Keras 库来分类手写数字。要安装 Auto-Keras 包,我们可以使用以下pip命令:
$ pip install autokeras
在撰写本书时,Auto-Keras 仅兼容 Python 3.6。对于安装过程,请参考官方网站autokeras.com/。
如何操作...
让我们看看如何使用 Auto-Keras:
- 创建一个新的 Python 文件并导入以下包(完整的代码已包含在您已提供的
AKClassifier.py文件中):
from keras.datasets import mnist
import autokeras as ak
- 让我们按照以下方式导入
mnist数据集:
(XTrain, YTrain), (XTest, YTest) = mnist.load_data()
- 在定义分类器之前,我们必须给包含输入数据的数组赋予新的形式,而不改变其内容:
XTrain = XTrain.reshape(XTrain.shape + (1,))
XTest = XTest.reshape(XTest.shape + (1,))
- 现在,我们可以构建分类器:
AKClf = ak.ImageClassifier()
- 然后,我们可以训练模型:
AKClf.fit(XTrain, YTrain)
- 最后,我们将使用未见过的数据(
XTest)来使用模型:
Results = AKClf.predict(XTest)
工作原理...
在本食谱中,我们仅用几行代码就构建了一个分类器,通过提供一系列手写数字的图像,可以正确地分类数字。
更多内容…
这是一个允许我们自动创建基于机器学习的算法的包,无需担心训练参数的设置,正如您在前几章中看到的,这些参数对于模型的成功至关重要。
参考信息
-
参考 Auto-Keras 库的官方文档:
autokeras.com/ -
参考 Haifeng Jin、Qingquan Song 和 Xia Hu 合著的《Auto-Keras: Efficient Neural Architecture Search with Network Morphism》(arXiv:1806.10282)。
使用 auto-sklearn
Auto-sklearn 在scikit-learn机器学习库上工作。它代表了一个基于监督机器学习的平台,可直接使用。它自动为新数据集搜索正确的机器学习算法并优化其超参数。
准备工作
在本食谱中,您将学习如何使用 auto-sklearn 构建分类器。为了导入数据,将使用sklearn.datasets.load_digits函数。此函数加载并返回用于分类问题的数字数据集。每个数据点是数字的 8x8 图像。
如何操作...
让我们看看如何使用 auto-sklearn:
- 创建一个新的 Python 文件并导入以下包(完整的代码已包含在您已提供的
ASKLClassifier.py文件中):
import autosklearn.classification
import sklearn.model_selection
import sklearn.datasets
import sklearn.metrics
- 让我们按照以下方式导入
digits数据集:
Input, Target = sklearn.datasets.load_digits()
- 让我们按照以下方式分割数据集:
XTrain, XTest, YTrain, YTest = sklearn.model_selection.train_test_split(Input, Target, random_state=3)
- 现在,我们可以构建分类器:
ASKModel = autosklearn.classification.AutoSklearnClassifier()
- 然后,我们可以训练模型:
ASKModel.fit(XTrain, YTrain)
- 最后,我们将使用未见过的数据(
XTest)来使用模型:
YPred = ASKModel.predict(XTest)
print("Accuracy score", sklearn.metrics.accuracy_score(YTest, YPred))
它是如何工作的...
Auto-sklearn 使用贝叶斯优化来调整scikit-learn中实现的传统机器学习算法的超参数。自动搜索最佳的机器学习算法和优化的参数。
还有更多...
Auto-sklearn 是一个很好的选择来自动化选择和优化自动学习模型的过程,因为它创建了极其精确的机器学习模型,避免了选择、训练和测试不同模型的繁琐任务。
参见
-
auto-sklearn包的官方文档:automl.github.io/auto-sklearn/stable/ -
由 Feurer 等人撰写的《高效且鲁棒的自动化机器学习》,发表于《神经信息处理系统进展》
使用 MLBox 进行选择和泄漏检测
MLBox 是一个机器学习的自动化库。它支持分布式数据处理、清理、格式化以及分类和回归的多种算法。它允许进行极其鲁棒的功能选择和泄漏检测。它还提供了堆叠模型,这意味着结合一组模型信息以生成一个旨在比单个模型表现更好的新模型。
准备工作
要使用这个库,必须先安装它。有关系统要求和安装过程的信息,请参阅mlbox.readthedocs.io/en/latest/installation.html。
在这个菜谱中,你将学习设置使用 MLBox 管道的严格必要条件。通过使用已经在第一章,“监督学习领域”中使用的波士顿数据集,我们将解决回归问题。
如何操作...
让我们看看如何使用 MLBox 进行选择和泄漏检测:
- 导入以下包(完整代码在已经为你提供的
MLBoxRegressor.py文件中):
from mlbox.preprocessing import *
from mlbox.optimisation import *
from mlbox.prediction import *
- 让我们导入数据,如下所示:
paths = ["train.csv","test.csv"]
target_name = "SalePrice"
使用此代码,我们已经设置了数据集的路径列表以及我们试图预测的目标名称。
- 现在,我们将读取和预处理这些文件:
data = Reader(sep=",").train_test_split(paths, target_name)
data = Drift_thresholder().fit_transform(data)
- 为了评估模型,将使用以下代码:
Optimiser().evaluate(None, data)
在这种情况下,使用了默认配置。
- 最后,为了在测试集上进行预测,使用以下代码:
Predictor().fit_predict(None, data)
如果你想要配置管道(步骤、参数和值),必须使用以下可选步骤。
- 为了测试和优化整个管道,我们将使用以下代码:
space = {
'ne__numerical_strategy' : {"space" : [0, 'mean']},
'ce__strategy' : {"space" : ["label_encoding", "random_projection", "entity_embedding"]},
'fs__strategy' : {"space" : ["variance", "rf_feature_importance"]},
'fs__threshold': {"search" : "choice", "space" : [0.1, 0.2, 0.3]},
'est__strategy' : {"space" : ["XGBoost"]},
'est__max_depth' : {"search" : "choice", "space" : [5,6]},
'est__subsample' : {"search" : "uniform", "space" : [0.6,0.9]}
}
best = opt.optimise(space, data, max_evals = 5)
- 最后,为了在测试集上进行预测,我们将使用以下代码:
Predictor().fit_predict(best, data)
它是如何工作的...
MLBox 通过以下三个步骤构建整个管道:
-
预处理:与这一阶段相关的所有操作都使用了
mlbox.preprocessing子包。在这一阶段,我们进行输入文件的读取和清理,然后移除漂移变量。 -
优化:与这一阶段相关的所有操作都使用了
mlbox.mlbox.optimisation子包。在这一阶段,整个流程被优化。采用的超参数优化方法使用了hyperopt库。这个库为要优化的参数创建了一个高维空间,并选择最佳参数组合以降低验证分数。 -
预测:与这一阶段相关的所有操作都使用了
mlbox.prediction子包。在这一阶段,我们使用测试数据和前一个阶段中确定的最佳超参数进行预测。
还有更多...
MLBox 提供了高级算法和技术,如超参数优化、堆叠、深度学习、泄漏检测、实体嵌入、并行处理等。目前,MLBox 的使用仅限于 Linux。MLBox 最初是用 Python 2 开发的,后来扩展到了 Python 3。
参考阅读
基于迁移学习的卷积神经网络
迁移学习是一种基于机器学习的方法,它利用在解决问题的过程中获得的知识记忆,并将其应用于不同(但相关)的问题。当训练数据供应有限时,就需要使用迁移学习。这可能是因为数据稀缺或收集、标记成本高昂,或者难以获取。随着大量数据的日益增多,迁移学习选项的使用频率越来越高。
卷积神经网络(CNNs)本质上是一种人工神经网络(ANNs)。实际上,就像后者一样,CNNs 由通过加权分支(权重)相互连接的神经元组成;网络的训练参数再次是权重和偏差。在 CNNs 中,神经元之间的连接模式受到了动物世界中视觉皮层结构的启发。大脑的这一部分(视觉皮层)中的单个神经元对观察到的某个狭窄区域的特定刺激做出反应,这个区域被称为感受野。不同神经元的感受野部分重叠,以覆盖整个视野。单个神经元对其感受野内发生的刺激的反应可以通过卷积运算进行数学近似。
准备工作
在这个菜谱中,你将学习如何使用 Keras 中的迁移学习来构建图像识别模型。为此,我们将使用 MobileNet 模型和 Keras 高级神经网络 API 来训练从Caltech256数据集中提取的模型图像,我们在第十章图像内容分析中已经使用过这个数据集。Caltech256在这个领域非常受欢迎!它包含 256 个类别的图像,每个类别包含数千个样本。
如何做到...
让我们使用 Keras 中的迁移学习来构建一个图像识别模型;在本节中,我们将逐步解释代码:
- 创建一个新的 Python 文件并导入以下包(完整的代码在已经为你提供的
ImageTransferLearning.py文件中):
from keras.layers import Dense,GlobalAveragePooling2D
from keras.applications import MobileNet
from keras.applications.mobilenet import preprocess_input
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Model
- 让我们导入
MobileNet模型并丢弃最后的 1,000 个神经元层:
BasicModel=MobileNet(input_shape=(224, 224, 3), weights='imagenet',include_top=False)
- 让我们定义 Keras 模型架构:
ModelLayers=BasicModel.output
ModelLayers=GlobalAveragePooling2D()(ModelLayers)
ModelLayers=Dense(1024,activation='relu')(ModelLayers)
ModelLayers=Dense(1024,activation='relu')(ModelLayers)
ModelLayers=Dense(512,activation='relu')(ModelLayers)
OutpModel=Dense(3,activation='softmax')(ModelLayers)
- 现在,我们可以基于之前定义的架构构建一个模型:
ConvModel=Model(inputs=BasicModel.input,outputs=OutpModel)
- 现在,我们可以进入训练阶段。由于采用了基于迁移学习的方法,因此没有必要对整个模型进行训练。这是因为 MobileNet 已经训练好了。让我们定义最后的密集层为可训练层:
for layer in ConvModel.layers[:20]:
layer.trainable=False
for layer in ConvModel.layers[20:]:
layer.trainable=True
- 让我们将训练数据加载到
ImageDataGenerator中:
TrainDataGen=ImageDataGenerator(preprocessing_function=preprocess_input)
ImageDataGenerator是一个内置的 Keras 类,它创建具有实时数据增强的 tensor 图像数据组。数据将以组的形式被卷绕。
- 让我们定义一些依赖项和训练数据的路径:
TrainGenerator=TrainDataGen.flow_from_directory('training_images/', #'train/'
target_size=(224,224),
color_mode='rgb',
batch_size=32,
class_mode='categorical',
shuffle=True)
- 让我们编译 Keras 模型:
ConvModel.compile(optimizer='Adam',loss='categorical_crossentropy',metrics=['accuracy'])
以下三个参数被传递:
-
optimizer='adam':这是一个基于自适应低阶矩估计的一阶、基于梯度的随机目标函数优化算法。 -
loss='categorical_crossentropy':我们在这里使用了categorical_crossentropy参数。当使用categorical_crossentropy,你的目标应该以分类格式(我们有 10 个类别;每个样本的目标必须是一个 10 维向量,除了对应于样本类别的索引处有一个 1 之外,其余都是 0)。 -
metrics=['accuracy']:一个指标是一个在训练和测试期间用于评估模型性能的函数。
- 最后,我们将定义训练的步长并拟合模型,如下所示:
StepSizeTrain=TrainGenerator.n//TrainGenerator.batch_size
ConvModel.fit_generator(generator=TrainGenerator,
steps_per_epoch=StepSizeTrain,
epochs=10)
打印以下结果:
Found 60 images belonging to 3 classes.
Epoch 1/10
1/1 [==============================] - 31s 31s/step - loss: 1.1935 - acc: 0.3125
Epoch 2/10
1/1 [==============================] - 21s 21s/step - loss: 2.7700 - acc: 0.5714
Epoch 3/10
1/1 [==============================] - 24s 24s/step - loss: 0.0639 - acc: 1.0000
Epoch 4/10
1/1 [==============================] - 21s 21s/step - loss: 0.2819 - acc: 0.7500
Epoch 5/10
1/1 [==============================] - 26s 26s/step - loss: 0.0012 - acc: 1.0000
Epoch 6/10
1/1 [==============================] - 21s 21s/step - loss: 0.0024 - acc: 1.0000
Epoch 7/10
1/1 [==============================] - 22s 22s/step - loss: 8.7767e-04 - acc: 1.0000
Epoch 8/10
1/1 [==============================] - 24s 24s/step - loss: 1.3191e-04 - acc: 1.0000
Epoch 9/10
1/1 [==============================] - 25s 25s/step - loss: 9.6636e-04 - acc: 1.0000
Epoch 10/10
1/1 [==============================] - 21s 21s/step - loss: 3.2019e-04 - acc: 1.0000
它是如何工作的...
在这个菜谱中,你学习了如何在图像识别问题中使用迁移学习。通过迁移学习,可以在大型且可访问的数据集上使用预训练模型,以找到具有可重用特征的输出层,这是通过使用这些输出作为输入来训练一个需要较少参数的较小网络来完成的。这个网络只需要知道从预训练模型获得的模式之间的关系以及要解决的特定问题。作为一个预训练模型,我们使用了 MobileNet 模型。
MobileNet 是由谷歌提出的一种架构,特别适合于基于视觉的应用。与具有相同深度网络的普通卷积相比,MobileNet 使用深度可分离卷积,显著减少了参数数量。因此,基于 MobileNet 模型的神经网络更轻。普通卷积被深度卷积替换,随后是一个称为深度可分离卷积的局部卷积。
迁移学习过程随后分为两个阶段:
-
首先,几乎所有的神经网络层都在一个非常大且通用的数据集上进行了训练,以便获取全局概念
-
后来,我们使用了特定的数据集来训练剩余的层,并决定是否通过微调传播错误
还有更多…
在这个配方中,我们使用了微调;实际上,我们并没有简单地替换最终层,我们还训练了一些之前的层。在我们使用的网络中,初始层被用来获取通用功能(利用 MobileNet 训练网络的潜力),而后续层被用来最终确定特定活动获得的经验。使用这个程序,我们冻结了前 20 层,同时追踪后续层以满足我们的需求。这种方法有助于在更少的训练时间内实现更好的性能。
微调可以通过以下步骤实现:
-
我们从一个在类似问题上预训练的网络开始,通过调整类别数量来替换输出层。
-
权重的初始值是预训练网络的值,除了连续层之间的连接,其权重是随机初始化的。
-
我们针对新数据集的独特性(不需要很大)进行新的训练迭代(SGD),以优化权重。
在微调过程中,模型参数将被精确调整以适应某些观察结果。
参考以下内容
-
参考 Keras 应用模型:
keras.io/applications/ -
参考以下内容:《MobileNets:适用于移动视觉应用的效率卷积神经网络》:
arxiv.org/pdf/1704.04861.pdf -
参考以下内容:《迁移学习与计算机视觉》(耶鲁大学):
euler.stat.yale.edu/~tba3/stat665/lectures/lec18/lecture18.pdf -
参考以下内容:《迁移学习综述》,S. J. Pan 和 Q. Yang,发表在《IEEE 知识数据工程杂志》:
www.cse.ust.hk/~qyang/Docs/2009/tkde_transfer_learning.pdf
使用 ResNet-50 预训练图像分类器进行迁移学习
残差网络(ResNet)代表了一种架构,通过使用新的创新类型的块(称为残差块)和残差学习的概念,使得研究人员能够达到经典前馈模型因梯度退化问题而无法达到的深度。
预训练模型是在大量数据上训练的,因此它们允许我们获得优异的性能。因此,我们可以采用与我们要解决的问题相似的预训练模型,以避免数据不足的问题。由于形成此类模型的计算成本,它们以可用的格式提供。例如,Keras 库提供了 Xception、VGG16、VGG19、ResNet、ResNetV2、ResNeXt、InceptionV3、InceptionResNetV2、MobileNet、MobileNetV2、DenseNet 和 NASNet 等模型。
准备工作
在这个菜谱中,你将学习如何使用预训练模型来预测单个图像的类别。为此,将使用 ResNet-50 模型。此模型来自keras.applications库。
如何做...
现在,我们将使用一个预训练模型来对单个图像进行分类;在本节中,我们将逐步解释代码:
- 创建一个新的 Python 文件并导入以下包(完整的代码在已经为你提供的
PretrainedImageClassifier.py文件中):
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np
- 让我们定义预训练模型:
PTModel = ResNet50(weights='imagenet')
- 让我们定义要分类的图像:
ImgPath = 'airplane.jpg'
Img = image.load_img(ImgPath, target_size=(224, 224))
- 在这里,我们将一个图像实例转换为一个
numpy数组,数据类型为float32:
InputIMG = image.img_to_array(Img)
- 现在,我们将获得的
numpy数组扩展到预训练模型所需的形状:
InputIMG = np.expand_dims(InputIMG, axis=0)
- 然后,我们将预处理数据:
InputIMG = preprocess_input(InputIMG)
- 最后,我们将使用预训练模型对输入图像进行分类:
PredData = PTModel.predict(InputIMG)
- 为了评估模型性能,我们将使用
decode_predictions函数,如下所示:
print('Predicted:', decode_predictions(PredData, top=3)[0])
keras.applications.resnet50.decode_predictions函数将结果解码为一个包含元组的列表(类别、描述和概率)。以下结果被打印出来:
Predicted: [('n02690373', 'airliner', 0.80847234), ('n04592741', 'wing', 0.17411195), ('n04552348', 'warplane', 0.008112171)]
较高的概率(0.80847234)告诉我们它是一架飞机;事实上,以下就是作为输入提供的图像:
它是如何工作的...
而不是试图估计一个函数G,该函数给定一个x,返回G(x),ResNet 学习这两个值之间的差异——一个称为残差的值。在网络中的残差层,发生了一个经典的卷积,并将输入加到结果上。如果输入和输出的大小不同,输入在添加到输出之前会通过另一个 1×1 滤波器卷积进行转换,以确保它具有相同的特征图数量。通过填充来保留特征图的大小。这种技术的优点是,L2 正则化,它倾向于将权重推向零,不会让我们忘记之前学到的内容,而只是简单地保留它。
还有更多…
有不同深度的 ResNet 实现;最深的达到 152 层。还有一个 1,202 层的原型,但由于过拟合,它实现了更差的结果。这个架构赢得了 2015 年 ILSVRC,错误率为 3.6%。为了理解这个结果的价值,只需考虑人类通常能达到的错误率大约在 5-10%,这取决于他们的技能和知识。多亏了这些结果,ResNet 模型目前在计算机视觉领域是当前最先进的。
相关内容
-
keras.applications模型的官方文档:keras.io/applications/ -
《深度残差学习用于图像识别》(由 Kaiming He、Xiangyu Zhang、Shaoqing Ren 和 Jian Sun 著):
arxiv.org/abs/1512.03385 -
预训练模型(来自多伦多大学):
www.cs.toronto.edu/~frossard/tags/pre-trained-models/
使用 VGG16 模型进行特征提取的迁移学习
如我们在第十四章的使用 PCA 和 t-SNE 可视化 MNIST 数据集食谱中所述,在重要维度的数据集中,数据被转换成一系列的表示函数。这个过程将输入数据转换成一系列功能,被称为特征提取。这是因为特征的提取是从一系列初始测量数据开始的,并产生导出的值,这些值可以保留原始数据集中的信息,但排除冗余数据。在图像的情况下,特征提取的目标是获取计算机可以识别的信息。
准备工作
在这个食谱中,你将学习如何从一系列图像中提取特征。然后,我们将使用这些特征通过 k-means 算法对图像进行分类。在这个食谱中,我们将使用 VGG16 预训练模型和klearn.cluster.KMeans函数。
如何操作...
让我们使用 VGG16 模型执行特征提取过程:
- 创建一个新的 Python 文件并导入以下包(完整的代码在已经为你提供的
ExtractFeatures.py文件中):
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np
from sklearn.cluster import KMeans
- 让我们定义预训练模型:
model = VGG16(weights='imagenet', include_top=False)
- 让我们初始化将要提取的特征列表:
VGG16FeatureList = []
- 对于数据集中的每个图像,我们必须进行特征提取:
import os
for path, subdirs, files in os.walk('training_images'):
for name in files:
img_path = os.path.join(path, name)
print(img_path)
这样,我们已经恢复了文件夹中每个图像的路径。所使用的图像包含在training_images文件夹中,我们在使用迁移学习的卷积神经网络食谱中已经使用过它。这是一系列从Caltech256数据集中提取的图像。
- 让我们按照以下方式导入图像:
img = image.load_img(img_path, target_size=(224, 224))
- 我们将取一个图像实例并将其转换为
float32类型的 NumPy 数组:
img_data = image.img_to_array(img)
- 现在,我们将根据预训练模型所需形状扩展获得的 NumPy 数组:
img_data = np.expand_dims(img_data, axis=0)
- 然后,我们将预处理数据:
img_data = preprocess_input(img_data)
- 我们将使用预训练模型从输入图像中提取特征:
VGG16Feature = model.predict(img_data)
- 在这一点上,我们将创建一个包含获取到的特征的数组:
VGG16FeatureNp = np.array(VGG16Feature)
- 现在,我们将获得的数组添加到我们正在构建的特征列表中(每个图像一个元素):
VGG16FeatureList.append(VGG16FeatureNp.flatten())
- 我们将最终列表转换为数组:
VGG16FeatureListNp = np.array(VGG16FeatureList)
- 现在,我们可以使用从图像中获得的特征按类型对它们进行分组。记住,这些图像来自三个类别:飞机、汽车和摩托车。因此,我们预计图像将被标记为三个不同的标签。为此,我们使用以下
KMeans算法:
KmeansModel = KMeans(n_clusters=3, random_state=0)
- 在定义模型后,我们继续训练它:
KmeansModel.fit(VGG16FeatureListNp)
- 最后,我们打印出所使用图像的标签:
print(KmeansModel.labels_)
以下结果被打印出来:
[2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
如你所见,60 张图像已经正确地标记在三个可用的类别中。
它是如何工作的……
在这个菜谱中,你学习了如何从一系列图像中提取特征。由于我们可用的图像数量有限,我们使用了预训练模型(VGG16)来正确提取后续识别所需的信息。这个程序有助于理解如何通过无监督模型自动识别图像。在提取特征后,我们使用它们通过 KMeans 算法对图像进行分类。
还有更多……
VGG16 是由牛津大学的 K. Simonyan 和 A. Zisserman 提出的一种卷积神经网络模型,在论文非常深的卷积神经网络在大规模图像识别中的应用中进行了介绍。该模型在图像识别(准确率达到 92.7%)方面取得了优异的成绩。测试是在 ImageNet 数据集上进行的,该数据集包含超过 1400 万张属于 1000 个类别的图像。
参见
-
参考第十四章中使用 PCA 和 t-SNE 可视化 Mnist 数据集的菜谱第十四章*,无监督表示学习*
-
参考论文非常深的卷积神经网络在大规模图像识别中的应用:
arxiv.org/abs/1409.1556
使用预训练 GloVe 嵌入的迁移学习
GloVe是一种用于获取单词向量表示的无监督学习算法。训练是在从代码文件中的文本中提取的单词共现的全球统计聚合上进行的。这些表示在单词的向量空间中显示出有趣的线性子结构。在这个菜谱中,你将学习如何使用预训练的 GloVe 嵌入模型来对形容词进行分类,以描述一个人的正面或负面特征。
准备工作
要遵循此食谱,您需要下载 glove.6B.100d.txt 文件。此文件可在 nlp.stanford.edu/projects/glove/ 获取。预训练的词向量有多个版本:
-
glove.6B: 6B 令牌,400K 词汇量,不区分大小写,50d、100d、200d 和 300d 向量——822 MB
-
glove.42B.300d: 42B 令牌,1.9M 词汇量,不区分大小写,300d 向量——1.75 GB
-
glove.840B.300d: 840B 令牌,2.2M 词汇量,区分大小写,300d 向量——2.03 GB
-
Twitter: 27B 令牌,1.2M 词汇量,不区分大小写,25d、50d、100d 和 200d 向量——1.42 GB
如何做到这一点...
让我们分类用于描述人的积极和消极态度的形容词:
- 创建一个新的 Python 文件并导入以下包(完整的代码已包含在您已提供的
PTGloveEMB.py文件中):
from numpy import array
from numpy import zeros
from numpy import asarray
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers import Embedding
- 让我们定义用于描述人的 10 个积极和 10 个消极形容词:
Adjectives = ['Wonderful',
'Heroic',
'Glamorous',
'Valuable',
'Excellent',
'Optimistic',
'Peaceful',
'Romantic',
'Loving',
'Faithful',
'Aggressive',
'Arrogant',
'Bossy',
'Boring',
'Careless',
'Selfish',
'Deceitful',
'Dishonest',
'Greedy',
'Impatient']
- 让我们定义之前定义的形容词的标签(
1= 积极,0= 消极):
AdjLabels = array([1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0])
- 让我们分词形容词并准备词汇表:
TKN = Tokenizer()
TKN.fit_on_texts(Adjectives)
VocabSize = len(TKN.word_index) + 1
- 让我们将形容词编码为整数序列并将序列列表转换为二维 NumPy 数组:
EncodedAdjectives = TKN.texts_to_sequences(Adjectives)
PaddedAdjectives = pad_sequences(EncodedAdjectives, maxlen=4, padding='post')
- 让我们加载预训练模型:
EmbeddingsIndex = dict()
f = open('glove.6B.100d.txt',encoding="utf8")
for line in f:
Values = line.split()
Word = Values[0]
Coefs = asarray(Values[1:], dtype='float32')
EmbeddingsIndex[Word] = Coefs
f.close()
- 我们将为分词形容词创建一个权重矩阵:
EmbeddingMatrix = zeros((VocabSize, 100))
for word, i in TKN.word_index.items():
EmbeddingVector = EmbeddingsIndex.get(word)
if EmbeddingVector is not None:
EmbeddingMatrix[i] = EmbeddingVector
- 现在,我们准备好定义
keras顺序模型:
AdjModel = Sequential()
PTModel = Embedding(VocabSize, 100, weights=[EmbeddingMatrix], input_length=4, trainable=False)
AdjModel.add(PTModel)
AdjModel.add(Flatten())
AdjModel.add(Dense(1, activation='sigmoid'))
print(AdjModel.summary())
以下摘要将被打印:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_13 (Embedding) (None, 4, 100) 2100
_________________________________________________________________
flatten_10 (Flatten) (None, 400) 0
_________________________________________________________________
dense_17 (Dense) (None, 1) 401
=================================================================
Total params: 2,501
Trainable params: 401
Non-trainable params: 2,100
如您所见,只有部分参数已被训练。
- 让我们编译和拟合模型:
AdjModel.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
AdjModel.fit(PaddedAdjectives, AdjLabels, epochs=50, verbose=1)
- 最后,我们将评估模型的表现:
loss, accuracy = AdjModel.evaluate(PaddedAdjectives, AdjLabels, verbose=1)
print('Model Accuracy: %f' % (accuracy*100))
以下结果将被返回:
Model Accuracy: 100.000000
它是如何工作的...
为了定量捕捉区分积极形容词和消极形容词所必需的细微差别,模型必须将多个数字与词组合相关联。一组词的简单方法就是两个词向量之间的向量差。GloVe 被设计成尽可能紧密地捕捉由几个词并置所指定的意义。
还有更多…
在迁移学习中,网络的权重被调整和转移,以便我们可以使用这些知识来追求多个不同的目标。为了从迁移学习中获得良好的性能,必须满足某些条件:初始数据和最终数据集之间不应相差太大,并且它们必须共享相同的预处理操作。
到目前为止,您已经看到了如何将迁移学习的概念应用于实际案例的几个示例。实际上,在实践中,迁移学习有多种类型:归纳迁移学习、无监督迁移学习、归纳推理迁移学习 和 实例迁移学习。我们正在努力深化这些概念。
要了解这些方法之间的差异,我们将查看术语——领域和任务。通过术语领域,我们指的是网络使用的类型的数据,而通过术语任务,我们指的是网络打算做什么。我们还将使用术语源和目标来区分已经在大量数据上训练过的网络和我们打算构建的网络。
归纳迁移学习
监督机器学习中最简单的一种形式是归纳学习。它完全基于观察。给定一组初始的输入输出示例,智能体通过提出假设来重建迁移函数。智能体被设计用来观察与外部世界的交互。特别是,智能体会分析其决策的反馈。人工智能体的感知可以如下使用:
-
做出决策(反应性智能体)
-
提高智能体的决策能力(机器学习)
在归纳迁移学习方法中,两个网络(源网络和目标网络)处理的信息类型相同(图像、声音等),而网络执行的任务不同。在这种情况下,迁移学习的目的是利用在源网络的训练中恢复的归纳偏差来提高目标网络的表现。通过术语归纳偏差,我们指的是算法在训练阶段恢复的一系列关于数据分布的假设。
无监督迁移学习
在无监督迁移学习中,两个网络(源网络和目标网络)处理的信息类型相同(图像、声音等),而网络执行的任务不同,就像归纳迁移学习一样。这两种方法实质性的区别在于无监督迁移学习中没有可用的标记数据。
归纳迁移学习
在归纳迁移学习中,两个网络(源网络和目标网络)处理的信息不同,而网络执行的任务相似。这种方法基于归纳推理的概念,它将推理从特定的(训练)案例带到特定的案例(测试)。与需要先解决更一般的问题再解决更具体问题的归纳不同,在归纳中,我们试图得到我们真正需要的答案,而不是更一般的答案。
实例迁移学习
在源域和目标域完全相似的场景中很难找到。更可能的是,找到一部分数据,这部分数据与目标域的数据更接近,但位于源域,而源域的大小远大于目标域。在实例迁移学习中,我们寻找源域中与目标域有强相关性的训练样本。一旦找到,它们将在目标活动的学习阶段被重新使用;这样,分类的准确性就得到了提高。
参考以下内容
-
参考以下文献:《全局词向量表示》(作者:Jeffrey Pennington, Richard Socher, 和 Christopher D. Manning):
www.aclweb.org/anthology/D14-1162 -
参考以下文献:《迁移学习算法综述》(作者:Mohsen Kaboli):
hal.archives-ouvertes.fr/hal-01575126/document
第十六章:解锁生产问题
在本章中,我们将介绍以下菜谱:
-
处理非结构化数据
-
部署机器学习模型
-
跟踪生产中的更改
-
跟踪准确性以优化模型缩放
技术要求
为了处理本章中的菜谱,你需要以下文件(可在 GitHub 上找到):
-
UNData.py -
TextFile.txt
简介
在前面的章节中,我们已经广泛介绍了机器学习中使用的算法。我们看到了 Python 程序员可以使用的许多工具,以及他们如何构建能够预测或分类特定信息的算法。下一步是创建可以用于生产和随后营销的软件。
考虑到将软件用于营销需要解决包括硬件和软件方面的相当多的问题,这并不是一个小挑战。事实上,我们首先必须确定哪些类型的设备将托管该软件,然后选择最适合那种技术的编程平台。
处理非结构化数据
到目前为止,我们已经强调了在基于自动学习的模型创建中输入数据的重要性。特别是,我们已经看到在将数据提供给我们的算法之前,适当处理这些数据是多么重要。在我们开始生产工作之前,我们必须面对的另一个挑战是学习如何处理非结构化数据。非结构化数据是指没有任何方案的存储数据。一个例子是包含由最流行的文本编辑软件或多媒体文件生成的文本的文件,但这些非结构化数据也可以是电子邮件、PDF 等。非结构化数据与数据库的不同之处在于,它们可能有不规则性,这不允许你将它们编目或以特定过程存储。
准备工作
作为来源,我使用了马克·吐温的小说《哈克贝利·费恩历险记》中的一段,可以在 GitHub 上查看。
如您所见,这是一段非结构化文本。我们将在将结果以结构化形式保存之前处理此文本并删除不必要的元素。
如何做...
在这个菜谱中,我们将学习如何处理非结构化数据。按照以下步骤开始:
- 创建一个新的 Python 文件并导入以下包(完整的代码已在提供的
UNData.py文件中):
import re
- 让我们定义输入文件名:
input_file = 'TextFile.txt'
- 我们需要初始化包含数据的字典:
data = {}
- 现在,我们可以加载并打印数据:
data['Twain'] = open(input_file,'r').read()
print(data['Twain'])
- 让我们将数据转换为小写:
for k in data:
data[k] = data[k].lower()
- 让我们删除任何标点符号:
for k in data:
data[k] = re.sub(r'[-./?!,":;()\']',' ',data[k])
- 让我们删除数字:
for k in data:
data[k] = re.sub('[-|0-9]',' ',data[k])
- 让我们删除任何额外的空白字符:
for k in data:
data[k] = re.sub(' +',' ',data[k])
- 最后,我们将打印并将结果保存到
.csv文件中:
print('###########################')
print(data['Twain'])
with open('Twain.csv', 'w') as f:
for key in data.keys():
f.write("%s,%s\n"%(key,data[key]))
f.close()
以下截图显示了输入文件(左侧)和获得的结果(右侧):
它是如何工作的...
在本食谱中,我们学习了如何处理非结构化数据。为此,使用了马克·吐温小说中的一段文字。在加载文本后,去除了标点符号、数字和额外的空白空间。此外,所有文本都被转换成了小写。最后,结果存储在一个.csv文件中。
更多内容...
在本食谱中,我们解决了文本分析的问题,这代表了将非结构化文本转换为后续分析阶段有意义数据的过程。可以用于文本分析的技术有很多,我们在第七章分析文本数据,分析文本数据中处理了其中的一些。
相关内容
-
参考第七章 分析文本数据,分析文本数据
-
参考斯坦福大学提供的非结构化数据:
web.stanford.edu/class/cs102/lecturenotes/UnstructuredData.pdf
部署机器学习模型
将基于机器学习的项目投入生产并不容易。实际上,只有少数公司设法做到了,至少对于大型项目来说是这样。困难在于人工智能不是通过成品软件生产的。需要一个起始平台来实现自己的软件模型,遇到的问题与开发者通常遇到的问题不相似。软件工程的经典方法导致抽象,从而得到可以修改和改进的简单代码。不幸的是,在机器学习应用中很难追求抽象,就像很难控制机器学习的复杂性一样。最好的办法是关注一个具有所需功能的平台,同时允许您从机器学习的数学基础中退出。在本食谱中,我们将介绍 Amazon SageMaker 平台。
准备工作
Amazon SageMaker 是一项付费服务,但多亏了 AWS 免费使用计划,您可以在注册后的前两个月内免费使用 Amazon SageMaker。有关可用计费计划的更多信息,请查看以下链接:aws.amazon.com。
如何操作...
让我们看看如何利用 Amazon SageMaker:
- 首先,您需要登录到控制台:
- 使用以下示例笔记本之一启动笔记本实例:
-
通过连接到自定义数据源来更改该实例。
-
按照示例创建、形成和验证模型:
- 最后,按照屏幕上的步骤在生产环境中分发结果。
它是如何工作的...
Amazon SageMaker 是一个用于创建、训练和分发基于机器学习模型的完全托管服务。Amazon SageMaker 包含三个模块——构建、训练和部署。构建模块允许我们处理数据,实验算法,并查看输出。训练模块在大型规模上训练模型并优化它。最后,是部署模块,它允许我们以低延迟轻松测试模型的推理。
还有更多…
Amazon SageMaker 允许我们创建用于智能和预测应用的机器学习模型。从安全角度来看,Amazon SageMaker 加密了所有基于机器学习的脚本。对 API 和 Amazon SageMaker 控制台的请求通过安全连接(SSL)转发。我们可以使用 AWS 身份和访问管理自动分配训练和分发资源的访问权限。我们还可以使用 Bucket S3、Amazon SageMaker KMS 密钥来加密笔记本训练过程和端点的存储卷。
参见
- 参考 Amazon SageMaker 的官方文档:
docs.aws.amazon.com/en_us/sagemaker/latest/dg/whatis.html
跟踪生产中的变更
模型的分布不是终点——这只是开始。真正的问题从这里开始。我们无法控制真实环境中的数据。可能会发生变更,我们必须准备好在模型过时之前检测和更新我们的模型。监控对于确保我们的机器学习应用程序的可靠性、可用性和性能至关重要。在本食谱中,我们将讨论一些我们可以用来跟踪模型中发生变化的工具。
如何操作...
以下工具可用于监控 Amazon SageMaker 应用程序:
- Amazon CloudWatch:这个工具在 AWS 中可用,监控实时运行的资源和应用。可以收集和跟踪参数,可以创建自定义控制面板,并可以设置警报,当指定的参数达到指定的阈值时通知或采取行动。以下截图显示了 Amazon CloudWatch 的概述:
-
Amazon CloudWatch Logs:这个工具在 AWS 中可用,允许您监控、存储和访问来自 EC2、AWS CloudTrail 实例和其他来源的日志文件。CloudWatch 日志监控日志文件中的信息,并在达到某些阈值时发送通知。
-
AWS CloudTrail:这个工具在 AWS 中可用,检索由我们的账户创建的 API 调用和相关事件,并将日志文件返回到指定的 Amazon S3 存储桶。我们还可以检索有关调用服务的用户和账户的有用信息,并可以追踪调用发生的 IP 地址和时间。
它是如何工作的...
要监控 Amazon SageMaker,我们可以使用 Amazon CloudWatch,它实时收集原始数据并将其转换为可读的参数。这些统计数据保留 15 个月,以便您可以访问历史信息,并从更好的角度了解服务或 Web 应用程序的性能。然而,Amazon CloudWatch 控制台将搜索限制在最近两周内已更新的参数。这种限制允许您查看命名空间中最新的过程。还可以设置警报,控制某些阈值,并在达到这些阈值时发送通知或采取行动。
更多内容...
机器学习模型基于一组具有各种属性的输入训练数据。因此,检查模型训练所用的输入数据是否仍然适用于实际环境中的数据非常重要。数据变化可能是突然的,也可能是随着时间的推移逐渐变化。因此,识别变化模式并在事先纠正模型是至关重要的。一旦模型在生产环境中分发,就需要遵循下一道菜谱中提到的步骤,以保持我们的模型健康,并使其对最终用户有用。
参见
-
参考 Amazon CloudWatch 的官方文档:
docs.aws.amazon.com/cloudwatch/index.html -
参考 Amazon CloudWatch Logs 的官方文档:
docs.aws.amazon.com/en_us/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html -
参考 Amazon CloudTrail 的官方文档:
docs.aws.amazon.com/cloudtrail/index.html
跟踪准确性以优化模型扩展
正如我们在第十五章,“自动化机器学习和迁移学习”中看到的,大多数机器学习算法使用一系列参数来控制底层算法的功能。这些参数通常被称为超参数;它们的值影响训练模型的质量。自动模型优化是寻找算法一组超参数的过程,这些超参数提供最优模型。在本菜谱中,我们将学习如何使用 Amazon SageMaker 工具自动优化我们的模型。
如何操作...
要自动优化我们的模型,请按照以下步骤操作:
-
打开 Amazon SageMaker 控制台。
-
在左下角的导航面板中选择“端点”项目。
-
从可用的端点中选择您想要配置的端点。
-
选择您想要配置的变体并配置自动扩展。对于端点运行时设置,也要这样做。
-
输入每个实例每分钟的调用平均次数。为此,针对目标值进行操作。
-
输入每个冷却周期的秒数。
-
为了防止缩放策略删除变体实例,请选择禁用缩放选项。
-
点击 保存。
它是如何工作的...
超参数优化过程代表了回归的一个特殊情况。这个问题可以这样表述:有一组输入特征可用,然后这个过程优化一个针对采用参数的模型。只要它是由我们使用的算法定义的,参数的选择就是自由的。在亚马逊超参数优化过程中,SageMaker 试图找出哪些超参数组合更有可能产生最佳结果,并尝试执行训练过程来测试这些尝试。为此,首先测试这些超参数的第一组值,然后该过程使用回归来选择下一组要测试的值。
还有更多...
当你选择下一次训练过程的最佳超参数时,超参数优化会考虑你到目前为止对该问题的所有了解。在某些情况下,超参数优化过程可以选择一个点,该点可以产生迄今为止找到的最佳结果的增量改进。这样,该过程使用已知的结果。在其他情况下,你可以选择一组远离你已经测试过的超参数。这样,该过程探索空间并寻找尚未完全分析的新区域。在许多机器学习问题中,探索和利用之间的权衡是常见的。
参见
- 参考文档:自动缩放 Amazon SageMaker 模型:
docs.aws.amazon.com/en_us/sagemaker/latest/dg/endpoint-auto-scaling.html