本文概述
深度学习是一项已成为机器学习工作流程必不可少的部分的技术。利用并行计算能力和支持工具的改进, 曾经不切实际的复杂和深度神经网络现在变得可行。
Tensorflow, Torch和Deeplearning4j等功能强大且可访问的库的出现, 也为学术界和大型技术公司的研究部门之外的用户打开了开发之门。为了证明其无处不在的普及性, 华为和苹果等公司现在在其最新设备中包括专门针对深度学习进行了优化的处理器, 以支持深度学习应用程序。
深度学习已在众多领域证明了其强大功能。最值得注意的是, Google的AlphaGo可以在Go游戏中击败人类玩家, 该游戏令人难以置信的复杂性曾经被认为是计算机在与人类玩家竞争中不可逾越的障碍。索尼的Flow Machines项目开发了一种神经网络, 该网络可以以过去著名音乐家的风格创作音乐。苹果公司开发的安全功能FaceID使用深度学习来识别用户的脸部并跟踪用户脸部随时间的变化。
在本文中, 我们将深度学习应用于我最喜欢的两个主题:自然语言处理和葡萄酒。我们将建立一个模型, 以了解专家对自然语言葡萄酒的评价, 并推断出他们所评价的葡萄酒的种类。
NLP深度学习
深度学习已广泛用于自然语言处理(NLP)中, 因为它非常适合学习句子的复杂基础结构和各个单词的语义接近度。例如, 情绪分析的最新技术使用深度学习, 以捕获难以建模的语言概念, 例如否定和混合情绪。
深度学习相对于其他用于NLP的算法具有以下优势:
- 灵活的模型:深度学习模型比其他ML模型灵活得多。我们可以轻松地尝试不同的结构, 并根据需要添加和删除层。深度学习模型还允许构建具有灵活输出的模型。灵活性是开发非常适合理解复杂语言结构的模型的关键。对于开发NLP应用程序(例如翻译, 聊天机器人和文本到语音应用程序), 这也是必不可少的。
- 所需的领域知识更少:尽管开发一个好的深度学习模型当然需要一定的领域知识和直觉, 但深度学习算法自行学习功能层次结构的能力意味着开发人员不需要那么多的深度知识。开发深度学习NLP算法的问题空间。对于像自然语言这样复杂的问题空间, 这是一个非常受欢迎的优势。
- 持续学习更轻松:随着新数据的传入, 深度学习算法易于训练。某些机器学习算法要求通过模型发送整个数据集以进行更新, 这对于实时的大型数据集会造成问题。
今天的问题
今天, 我们将建立一个深度学习算法, 根据评论文本确定要评论的葡萄酒的品种。我们将在Kaggle用户zackthoutt提供的https://www.kaggle.com/zynicide/wine-reviews使用葡萄酒杂志数据集。
从概念上讲, 问题是, 我们可以进行像…这样的葡萄酒评论吗?
香气包括热带水果, 扫帚, 硫磺和干草本。口感并不过分表达, 提供未成熟的苹果, 柑橘和干鼠尾草, 并带有轻快的酸度。
……并意识到这是关于白色混合的?一些葡萄酒爱好者可能会发现苹果, 柑橘和明显酸度等白葡萄酒的明显信号, 但是我们可以训练我们的神经网络来识别这些信号吗?另外, 我们可以训练我们的神经网络来识别白色混合评论和品脱grigio评论之间的细微差别吗?
相似算法
我们今天正在处理的问题实质上是NLP分类问题。有几种NLP分类算法已应用于NLP中的各种问题。例如, 朴素贝叶斯已被用于各种垃圾邮件检测算法中, 而支持向量机(SVM)已被用于对文本进行分类, 例如医疗机构中的进度记录。实现这些算法的简单版本作为我们的深度学习模型的基准将很有趣。
朴素贝叶斯
针对NLP的朴素贝叶斯的一种流行实现方式是使用TF-IDF对文本进行预处理, 然后在预处理后的输出上运行多项朴素贝叶斯。这使算法可以在文档中最突出的单词上运行。我们可以如下实现朴素的贝叶斯:
import numpy as np
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
from collections import Counter
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfTransformer
df = pd.read_csv('data/wine_data.csv')
counter = Counter(df['variety'].tolist())
top_10_varieties = {i[0]: idx for idx, i in enumerate(counter.most_common(10))}
df = df[df['variety'].map(lambda x: x in top_10_varieties)]
description_list = df['description'].tolist()
varietal_list = [top_10_varieties[i] for i in df['variety'].tolist()]
varietal_list = np.array(varietal_list)
count_vect = CountVectorizer()
x_train_counts = count_vect.fit_transform(description_list)
tfidf_transformer = TfidfTransformer()
x_train_tfidf = tfidf_transformer.fit_transform(x_train_counts)
train_x, test_x, train_y, test_y = train_test_split(x_train_tfidf, varietal_list, test_size=0.3)
clf = MultinomialNB().fit(train_x, train_y)
y_score = clf.predict(test_x)
n_right = 0
for i in range(len(y_score)):
if y_score[i] == test_y[i]:
n_right += 1
print("Accuracy: %.2f%%" % ((n_right/float(len(test_y)) * 100)))
运行上面的代码, 你应该看到类似以下内容:73.56%
考虑到我们正在上10堂课, 这是相当不错的成绩。
我们还可以使用支持向量机, 看看它会怎么做。要查看其性能, 只需将分类器定义替换为
clf = SVC(kernel='linear').fit(train_x, train_y)
运行此命令, 你应该看到以下输出:
准确度:80.66%
也不要太破旧。
让我们看看我们是否可以建立一个可以超过或至少匹配这些结果的深度学习模型。如果我们能够做到这一点, 那将很好地表明我们的深度学习模型至少可以有效地复制由领域专业知识告知的流行机器学习模型的结果。
建立模型
今天, 我们将结合使用Tensorflow和Keras来构建模型。 Keras是一个Python库, 与Tensorflow API的相对底层接口相比, 它使构建深度学习模型非常容易。除了密集层之外, 我们还将使用嵌入和卷积层来学习单词的潜在语义信息和数据中的潜在结构模式。
数据清理
首先, 我们将必须以一种易于被我们的神经网络处理和理解的方式来重组数据。我们可以通过用唯一标识数字替换单词来做到这一点。结合嵌入向量, 我们能够以灵活且语义敏感的方式表示单词。
在实践中, 我们希望对这种预处理更加了解。将重点放在常用词上, 并过滤掉最常用的词(例如, the, this, a), 将是有意义的。
我们可以使用Defaultdict和NLTK来实现此功能。将以下代码编写到单独的Python模块中。我把它放在lib / get_top_x_words.py中。
from nltk import word_tokenize
from collections import defaultdict
def count_top_x_words(corpus, top_x, skip_top_n):
count = defaultdict(lambda: 0)
for c in corpus:
for w in word_tokenize(c):
count[w] += 1
count_tuples = sorted([(w, c) for w, c in count.items()], key=lambda x: x[1], reverse=True)
return [i[0] for i in count_tuples[skip_top_n: skip_top_n + top_x]]
def replace_top_x_words_with_vectors(corpus, top_x):
topx_dict = {top_x[i]: i for i in range(len(top_x))}
return [
[topx_dict[w] for w in word_tokenize(s) if w in topx_dict]
for s in corpus
], topx_dict
def filter_to_top_x(corpus, n_top, skip_n_top=0):
top_x = count_top_x_words(corpus, n_top, skip_n_top)
return replace_top_x_words_with_vectors(corpus, top_x)
现在我们准备建立模型。我们想要一个嵌入层, 一个卷积层和一个密集层来利用所有可能对我们的应用程序有帮助的深度学习功能。使用Keras, 我们可以非常简单地构建模型:
from keras.models import Sequential
from keras.layers import Dense, Conv1D, Flatten
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
from keras.utils import to_categorical
import pandas as pd
from collections import Counter
from sklearn.model_selection import train_test_split
from lib.get_top_xwords import filter_to_top_x
df = pd.read_csv('data/wine_data.csv')
counter = Counter(df['variety'].tolist())
top_10_varieties = {i[0]: idx for idx, i in enumerate(counter.most_common(10))}
df = df[df['variety'].map(lambda x: x in top_10_varieties)]
description_list = df['description'].tolist()
mapped_list, word_list = filter_to_top_x(description_list, 2500, 10)
varietal_list_o = [top_10_varieties[i] for i in df['variety'].tolist()]
varietal_list = to_categorical(varietal_list_o)
max_review_length = 150
mapped_list = sequence.pad_sequences(mapped_list, maxlen=max_review_length)
train_x, test_x, train_y, test_y = train_test_split(mapped_list, varietal_list, test_size=0.3)
max_review_length = 150
embedding_vector_length = 64
model = Sequential()
model.add(Embedding(2500, embedding_vector_length, input_length=max_review_length))
model.add(Conv1D(50, 5))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(max(varietal_list_o) + 1, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(train_x, train_y, epochs=3, batch_size=64)
y_score = model.predict(test_x)
y_score = [[1 if i == max(sc) else 0 for i in sc] for sc in y_score]
n_right = 0
for i in range(len(y_score)):
if all(y_score[i][j] == test_y[i][j] for j in range(len(y_score[i]))):
n_right += 1
print("Accuracy: %.2f%%" % ((n_right/float(len(test_y)) * 100)))
运行代码, 你应该看到以下输出。
准确度:77.20%
回想一下, 朴素贝叶斯和SVC的准确性分别为73.56%和80.66%。因此, 我们的神经网络非常依赖于其中一些较常见的文本分类方法。
总结
今天, 我们讨论了建立分类深度学习模型来分析葡萄酒评论。
我们发现我们能够建立一个能够与其他机器学习算法竞争并胜过其他机器学习算法的模型。我们希望你能启发使用此信息来构建应用程序, 以分析更复杂的数据集并生成更复杂的输出!
注意:你可以在GitHub上找到我用于本文的代码。
评论前必须登录!
注册