随着 NLP(自然语言解决)的最新进展,OpenAI 的 GPT- 3 曾经成为市场上最弱小的语言模型之一。2022 年 1 月 25 日,OpenAI 颁布了一个 embedding endpoint(Neelakantan et al.,2022)。该神经网络模型将文本和代码转换为向量示意,将它们嵌入到高维空间中。这些模型能够捕捉文本的语义相似性,并且在某些用例中仿佛实现了最先进的性能。
因为 chatgpt 的大火,GPT- 3 又进入到了人们的视线中,本文将通过应用 text-embedding-ada-002(GPT- 3 的一个 Embeddings,抉择该模型是因为它价格适中且应用简略),与三种传统文本嵌入技术生成的嵌入的性能进行比拟;GloVe(Pennington、Socher Manning,2014 年)、Word2vec(Mikolov,2013 年)和 MPNet(Song,2020 年)。这些嵌入将用于训练多个机器学习模型,应用 Amazon 美食评论数据集中的食品评论评分进行分类。每种嵌入技术的性能将通过比拟它们的准确性指标来评估。
数据筹备
本文中应用的数据集是来自 Amazon 美食评论数据集的 1000 个数据集的子集。这个子集蕴含了应用 GPT- 3 的“text- embedded -ada-002”模型曾经生成的嵌入。嵌入是由题目 (摘要) 和文本的组合生成的。如图 1 所示,每个评论还具备 ProductId、UserId、Score 和从组合文本生成的令牌数量。
# Libraries
fromsentence_transformersimportSentenceTransformer
fromsklearn.model_selectionimporttrain_test_split
fromsklearn.linear_modelimportLogisticRegression
fromsklearn.ensembleimportRandomForestClassifier
fromsklearn.metricsimportclassification_report
fromsklearn.treeimportDecisionTreeClassifier
fromsklearn.preprocessingimportRobustScaler
fromsklearn.pipelineimportPipeline
importgensim.downloaderasapi
fromsklearn.svmimportSVC
importpandasaspd
importnumpyasnp
importopenai
importre
# import data
df1=pd.read_csv('https://raw.githubusercontent.com/openai/openai-cookbook/main/examples/data/fine_food_reviews_with_embeddings_1k.csv',
index_col=0)
# view first three rows
df1.head(3)
对于换行符和空格会影响咱们将嵌入示意为数组。所以须要一个函数来删除不必要的字符并将嵌入转换为适当的数组格局。GPT- 3 嵌入变量的名称也将更改为 ’ gpt_3 ‘,这样能够区别本文前面生成的其余嵌入。
# clean openai embeddings
defclean_emb(text):
# remove line break
text=re.sub(r'\n', '', text)
# remove square brackets
text=re.sub(r'\[|\]', "", text)
# remove leading and trailing white spaces
text=text.strip()
# convert string into array
text=np.fromstring(text, dtype=float, sep=',')
returntext
# Rename column to gpt_3
df1.rename(columns={'embedding': 'gpt_3'}, inplace=True)
# Apply clean_emb function
df1['gpt_3'] =df1['gpt_3'].apply(lambdax: clean_emb(x))
GPT- 3 嵌入
数据集蕴含事后生成的基于 gpt - 3 的嵌入。然而咱们为了生成最新的嵌入,还须要一个 API 密钥来拜访模型。该密钥能够通过注册 OpenAI API 来取得。而后就是创立一个函数,指定要应用的模型(在本例中为 text-embedding-ada-002)。
api_key='api key'
# set api key as default api key for openai
openai.api_key=api_key
defget_embedding(text, model="text-embedding-ada-002"):
# replace new lines with spaces
text=text.replace("\n", " ")
# openai.Embedding.create to convert text into embedding array
returnopenai.Embedding.create(input= , model=model)['data'][0]['embedding']
因为都是获取 API 的返回后果,所以这个过程非常简单。
GloVe 嵌入
GloVe(用于词示意的全局向量)是一种文本嵌入技术,它依据词在大量文本中的共现统计来构建词的向量示意。GloVe 的想法是,在可比拟的状况下呈现的词在语义上是相干的,并且能够应用通过共现矩阵统计它们的共现来推断这些词之间的分割。
应用 spaCy 库能够轻松的生成基于 GloVe 的嵌入。这里咱们应用“en_core_web_lg”英语管道。该管道对给定的文本输出执行一系列步骤,例如标记化、标记和词形还原,以将其转换为适合的格局。该管道蕴含 514,000 个向量,对于以后的用例来说曾经足够大了。
GloVe 是 14 年公布的,尽管到当初都快 10 年了,然而在 transformers 呈现之前 GloVe 能够说是最胜利的词嵌入办法,所以这里咱们还是要拿他来进行以下比照
importspacy
# load pipeline
nlp=spacy.load("en_core_web_lg")
这里咱们也须要进行文本清理。如上图 2 所示,在第一个文本输出中间断呈现了一些句号。这种模式必须加以纠正。
df1.combined[0]
咱们创立一个函数,用单个句号替换间断的句号,并删除句子开端的空格。
defreplace_multiple_fullstops(text):
# replace 2 or more consecutive fullstops with 1
text=re.sub(r'\.{2,}', '.', text)
# strip white spaces from ends of sentence
text=text.strip()
returntext
# Apply function
df1['clean_text'] =df1['combined'].apply(lambdax: replace_multiple_fullstops(x))
而后就能够在清理过程之后生成嵌入。
df1['glove'] =df1['clean_text'].apply(lambdatext: nlp(text).vector)
Word2vec 嵌入
word2vec 技术是基于一个通过大量文本训练的神经网络模型,从其四周的上下文单词中预测指标单词。Word2vec 的工作原理是用一个间断向量来示意词汇表中的每个单词,该向量捕捉了应用该单词的含意和上下文。这些向量是通过无监督学习过程生成的,神经网络模型尝试预测给定高低的单词。
Gensim 库可用于加载在 word2vec 技术上训练的模型。Gensim 库中的“word2vic – Google – News -300”模型是在谷歌 News 数据集上训练的,该数据粗放有 1000 亿个单词,可能示意数据集中的大部分单词(。
importgensim.downloaderasapi
# Load word2vec-google-news-300 model
wv=api.load("word2vec-google-news-300")
因为 Gensim 库提供的是模型而不是管道,所以在应用 word2vec 模型生成向量示意之前,还须要应用 spaCy 库对文本输出进行标记化、清理和 lemm 化。
defwv_preprocess_and_vectorize(text):
# Process the input text using a natural language processing library
doc=nlp(text)
# Initialize a list to store the filtered tokens
filtered_tokens= []
# Loop through each token in the doc
fortokenindoc:
# If the token is a stop word or punctuation, skip it
iftoken.is_stoportoken.is_punct:
continue
# Otherwise, add the lemma of the token to the filtered_tokens list
filtered_tokens.append(token.lemma_)
# If there are no filtered tokens, return np.nan
ifnotfiltered_tokens:
returnnp.nan
else:
# Otherwise, return the mean vector representation of the filtered tokens
returnwv.get_mean_vector(filtered_tokens)
# Apply function
df1['word2vec'] =df1['clean_text'].apply(lambdatext: wv_preprocess_and_vectorize(text))
MPNet 嵌入(BERT)
MPNet(Masked and Permuted Language Model Pre-training)是一种用于 NLP 的基于 transformer 的语言模型预训练技术。MPNet 提供了 BERT 模型的变体。BERT 在预训练期间屏蔽一部分输出令牌,并训练模型依据未屏蔽令牌的上下文预测已屏蔽令牌。这个过程被称为掩码语言建模,它对于捕捉文本语料库中单词的含意和上下文是无效的。除了屏蔽语言建模之外,MPNet 还采纳了一种随机排列输出标记程序的排列机制。这种排列有助于模型学习输出序列中单词之间的全局上下文和关系。
咱们这里应用 hug Face 的句子转换模型“all-mpnet-base-v2”来获取基于 mpnet 的嵌入。该模型建设在 MPNet 根底模型的根底上,并对 10 亿句对数据集进行微调。
model_sent=SentenceTransformer('all-mpnet-base-v2')
df1['mpnet'] =df1['clean_text'].apply(lambdatext: model_sent.encode(text))
维度比拟
下图 3 显示了每种嵌入的不同维度。GPT- 3 的最大维度为 1536。而后是 MPNet、Word2vec 和 GloVe,别离为 768、300 和 300 维。
# assign data of lists.
data= {'Name': ['gpt_3', 'mpnet', 'word2vec', 'glove'],
'Dimension': [len(df1.gpt_3[0]), len(df1.mpnet[0]),
len(df1.word2vec[0]), len(df1.glove[0])]}
# Create DataFrame
df_emb_len=pd.DataFrame(data)
# Set background style
df_emb_len.style.background_gradient()
评估应用的模型
为了评估文本嵌入的性能,咱们应用了四个分类器; 随机森林、反对向量机、逻辑回归和决策树对 Score 变量进行预测。数据集将被分成 75:25 的训练与测试集来评估准确性。因为嵌入是二维的,因而在训练之前将应用 numpy 函数将它们转换为单个三维数组。
# Define a list of embedding methods to evaluate
embedding_var= ['gpt_3', 'mpnet', 'word2vec', 'glove']
# Define a list of classifier models to use
classifiers= [('rf', RandomForestClassifier(random_state=76)),
('svm', SVC(random_state=76)),
('lr', LogisticRegression(random_state=76, max_iter=400)),
('dt', DecisionTreeClassifier(random_state=76))]
# Define a dictionary to store accuracy results for each classifier
accuracy_lists= {'rf': [],
'svm': [],
'lr': [],
'dt': []}
# Loop through each embedding method
forembinembedding_var:
# Split the data into training and testing sets using the 'train_test_split' function
X_train, X_test, y_train, y_test=train_test_split(df1[emb].values,
df1.Score,
test_size=0.25,
random_state=76
)
# Stack the training and testing sets into 3D arrays
X_train_stacked=np.stack(X_train)
X_test_stacked=np.stack(X_test)
# Loop through each classifier model
forclassifier_name, classifierinclassifiers:
# Create a pipeline that scales the data and fits the classifier
pipe=Pipeline([('scaler', RobustScaler()), (classifier_name, classifier)])
pipe.fit(X_train_stacked, y_train)
# Use the pipeline to make predictions on the test data
y_pred=pipe.predict(X_test_stacked)
# Evaluate the accuracy of the predictions
report=classification_report(y_test, y_pred ,output_dict=True)
acc=report['accuracy']
# Store the accuracy results for each classifier
accuracy_lists[classifier_name].append(acc)
后果
下图 4 所示,模型出现了一些乏味的后果。GPT- 3 嵌入在所有模型中取得了最高的精度。MPNet 嵌入在应用逻辑回归和反对向量机时体现次之,但在随机森林算法中被 word2vec 嵌入超过,在决策树算法中体现最差。对于维数对模型性能的影响,还不能得出明确的论断,然而从后果中能够显著看出,GPT- 3 嵌入始终优于所有其余嵌入,显示了其在文本分类方面的劣势。
# Add a new key 'embeddings' to the dictionary 'accuracy_lists' and assign the list 'embedding_var' to it
accuracy_lists['embeddings'] =embedding_var
# Create a list of tuples using the values from the dictionaries
df_zip=list(zip(accuracy_lists['embeddings'], accuracy_lists['lr'], accuracy_lists['svm'], accuracy_lists['rf'], accuracy_lists['dt']))
# Create a DataFrame 'df_accuracy' from the list 'df_zip' and specify the column names
df_accuracy=pd.DataFrame(df_zip, columns= ['Embedding','Logistic_Regression','Support_Vector_Machine', 'Random_Forest','Decision_Tree'])
# Add a background gradient to the DataFrame for visual representation
df_accuracy.style.background_gradient()
所以还是那句话 ” 别问,问就是 GPT3″😏
如果你想自行测试,本文的代码在这里:
https://avoid.overfit.cn/post/58e8c9b6ed3d44a0ba777f89d193f76e
作者:Derrick Owusu Ofori