当前位置: 首页 > 科技观察

简述三种表示句子的无监督深度学习方法

时间:2023-03-18 14:35:08 科技观察

近年来,由于单词的连续向量表示(而不是稀疏的单热编码向量(Word2Vec))的发展,在自然语言处理领域的表现有了很大的进步。Word2Vec示例尽管Word2Vec表现良好并创建了像King-Man+Woman=Queen这样的漂亮语义,但我们有时并不关心单词表示而是句子表示。本文将介绍几种用于句子表示的无监督深度学习方法,并分享相关代码。我们将展示这些方法在特定文本分类任务中作为预处理步骤的有效性。用于展示分类任务的不同句??子表示方法的数据基于从万维网上抓取的10,000篇新闻文章。分类任务是将每篇文章分类为10个可能的主题之一(数据有主题标签,所以这是一个有监督的任务)。出于演示目的,我将使用逻辑回归模型,每次对文章标题使用不同的预处理表示。基线模型——平均Word2Vec我们从一个简单的基线模型开始。我们将通过平均标题词的Word2Vec表示来表示文章标题。如前所述,Word2Vec是一种将单词表示为向量的机器学习方法。Word2Vec模型是通过使用浅层神经网络来预测接近目标词的词来训练的。您可以阅读有关此算法如何工作的更多信息:http://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/。我们可以使用Gensim来训练我们自己的Word2Vec模型,但在本例中,我们将使用基于Google新闻数据构建的Google预训练Word2Vec模型。在将每个单词表示为一个向量之后,我们将一个句子(文章标题)表示为其单词(向量)的平均值,并运行逻辑回归来对文章进行分类。#loaddataandWord2vecmodeldf=pd.read_csv("news_dataset.csv")data=df[['body','headline','category']]w2v=gensim.models.KeyedVectors.load_word2vec_format('/GoogleNews-vectors-negative300.bin',binary=True)#BuildXandYx=np.random.rand(len(data),300)foriinrange(len(data)):k=0non=0values=np.zeros(300)forjindata['headline'].iloc[i].split(''):ifjinw2v:values+=w2v[j]k+=1ifk>0:x[i,:]=values/kelse:non+=1y=LabelEncoder().fit_transform(数据['类别'].values)msk=np.random.rand(len(data))<0.8X_train,y_train,X_test,y_test=x[msk],y[msk],x[~msk],y[~msk]#Trainthemodellr=LogisticRegression().fit(X_train,y_train)lr.score(X_test,y_test)我们的基线平均Word2Vec模型达到了68%的准确率。这很酷,所以让我们看看我们是否可以做得更好。一般的Word2Vec方法有两个弱点:它是词袋模型,与词序无关,所有词具有相同的权重。对于句子表示,我们在以下方法中使用RNN架构解决了这些问题。自动编码器自动编码器是一种无监督的深度学习模型,它试图将自己的输入复制到输出。自动编码器的技巧是中间隐藏层的维数低于输入数据。因此,这种神经网络必须以智能、紧凑的方式表示输入,才能成功重建。使用自动编码器进行特征提取已被证明在许多情况下非常有效。我们的自动编码器是一个简单的序列到序列结构,由输入层、嵌入层、LSTM层和softmax层组成。整个结构的输入输出就是标题,我们会用LSTM的输出来表示标题。从自动编码器获得表示后,我们将使用逻辑回归来预测类别。为了获得更多的数据,我们将使用文章中的所有句子来训练自动编码器,而不是仅仅使用文章标题。#parseallsentencessentenses=[]foriindata['body'].values:forjinnltk.sent_tokenize(i):sentenses.append(j)#preprocessforkerasnum_words=2000maxlen=20tokenizer=Tokenizer(num_wordsnum_words=num_words,split='')tokenizer.fit_on_texts(句子)seqs=tokenizer.texts_to_sequences(sentenses)pad_seqs=[]foriinseqs:iflen(i)>4:pad_seqs.append(i)pad_seqs=pad_sequences(pad_seqs,maxlen)#Themodelembed_dim=150latent_dim=128batch_size=64####EncoderModel####encoder_inputs=输入(shape=(maxlen,),name='Encoder-Input')emb_layer=Embedding(num_words,embed_dim,input_length=maxlen,name='Body-Word-Embedding',mask_zero=False)#Wordembedingforencoder(ex:IssueBody)x=emb_layer(encoder_inputs)state_h=GRU(latent_dim,name='Encoder-Last-GRU')(x)encoder_model=Model(inputs=encoder_inputs,outputs=state_h,name='Encoder-Model')seq2seq_encoder_out=encoder_model(encoder_inputs)####解码器模型####decoded=RepeatVector(maxlen)(seq2seq_encoder_out)decoder_gru=GRU(latent_dim,return_sequences=True,name='Decoder-GRU-before')decoder_grudecoder_gru_output=decoder_gru(解码)decoder_dense=Dense(num_words,activation='softmax',name='Final-Output-Dense-before')decoder_outputs=decoder_dense(decoder_gru_output)##没有.fit(pad_seqs,np.expand_dims(pad_seqs,-1),batch_sizebatch_size=batch_size,epochs=5,validation_split=0.12)#Featureextractionheadlines=tokenizer.texts_to_sequences(data['headline'].values)headlines=pad_sequencesmax(maxlenheadlines,=maxlen)x=encoder_model.predict(标题)#classifierX_train,y_train,X_test,y_test=x[msk],y[msk],x[~msk],y[~msk]lr=LogisticRegression().fit(X_train,y_train)lr.score(X_test,y_test)我们达到了60%的准确率,比基线模型差。我们可以通过优化超参数、增加训练时期的数量或在更多数据上训练模型来改进这一点。分数。语言模型我们的第二种方法是训练一个语言模型来表示句子。语言模型描述了某种语言的文本的概率。例如,“我喜欢吃香蕉”这句话比“我喜欢吃卷心菜”这句话存在的概率要高。我们通过拆分n个单词的窗口并预测文本中的下一个单词来训练语言模型。您可以在此处阅读有关基于RNN的语言模型的更多信息:http://karpathy.github.io/2015/05/21/rnn-effectiveness/。通过构建语言模型,我们了解了“新闻英语”是如何构建的,该模型应该关注重要的词及其表示。我们的架构类似于自动编码器的架构,但我们只预测单个单词,而不是单词序列。输入将包含由新闻文章中的20个单词组成的窗口,标签为第21个单词。训练完语言模型后,我们会从LSTM的输出隐藏状态中得到标题表示,然后运行逻辑回归模型来预测类别。#BuildingXandYnum_words=2000maxlen=20tokenizer=分词器(num_wordsnum_words=num_words,split='')tokenizer.fit_on_texts(df['body'].values)seqs=tokenizer.texts_to_sequences(df['body'].values)seq=[]foriinseqs:seq+=iX=[]Y=[]foriintqdm(范围(len(seq)-maxlen-1)):X.append(seq[i:i+maxlen])Y.append(seq[i+maxlen+1])X=pd.DataFrame(X)Y=pd.DataFrame(Y)Y[0]=Y[0].astype('category')Y=pd.get_dummies(Y)#Buidlingthenetworkembed_dim=150lstm_out=128batch_size=128model=顺序()model.add(嵌入(num_words,embed_dim,input_length=maxlen))model.add(双向(LSTM(lstm_out)))model.add(密集(Y.shape[1],activation='softmax'))adam=Adam(lr=0.001,beta_1=0.7,beta_2=0.99,epsilon=None,decay=0.0,amsgrad=False)model.compile(loss='categorical_crossentropy',optimizer=adam)model.summary()打印('适合')model.fit(X,Y,batch_sizebatch_size=batch_size,validation_split=0.1,epochs=5,verbose=1)#Featureextractionheadlines=tokenizer.texts_to_sequences(data['headline'].values)headlines=pad_sequences(headlines,maxlenmaxlen=maxlen)inp=model.inputoutputs=[model.layers[1].output]functor=K.function([inp]+[K.learning_phase()],outputs)x=functor([标题,1.])[0]#classifierX_train,y_train,X_test,y_test=x[msk],y[msk],x[~msk],y[~msk]lr=LogisticRegression().fit(X_train,y_train)lr.score(X_test,y_test)这次我们得到了72%的准确率,比基线模型要好,那我们能不能做得更好呢?Skip-Thoughtvectormodelin2015aboutskip-thought在论文《Skip-Thought Vectors》中,作者从语言模型中得到了同样的直觉。然而,在skip-thought中,我们不是预测下一个词,而是预测前后的句子。这为模型提供了更多关于句子的上下文,因此我们可以构建更好的句子表示。您可以阅读此博客(https://medium.com/@sanyamagarwal/my-thoughts-on-skip-thoughts-a3e773605efa)以了解有关此模型的更多信息。skip-thought论文(https://arxiv.org/abs/1506.06726)中的示例我们将构造一个类似于自动编码器的序列到序列结构,但它与自动编码器有两个主要区别。***,我们有两个LSTM输出层:一个用于上一句,一个用于下一句;其次,我们将在输出LSTM中使用教师强制。这意味着我们不仅向输出LSTM提供了先前的隐藏状态,而且还提供了实际的先前单词(参见上面的输入和输出的第一行)。#Buildxandynum_words=2000maxlen=20tokenizer=分词器(num_wordsnum_words=num_words,split='')tokenizer.fit_on_texts(sentenses)seqs=tokenizer.texts_to_sequences(sentenses)pad_seqs=pad_sequences(seqs,maxlen)x_skip=[]y_before=[]y_after=[]foriintqdm(范围(1,len(seqs)-1)):iflen(seqs[i])>4:x_skip.append(pad_seqs[i].tolist())y_before.append(pad_seqs[i-1].tolist())y_after.append(pad_seqs[i+1].tolist())x_before=np.matrix([[0]+i[:-1]foriiny_before])x_after=np.matrix([[0]+i[:-1]foriiny_after])x_skip=np.matrix(x_skip)y_before=np.matrix(y_before)y_after=np.matrix(y_after)#Buildingthemodelembed_dim=150latent_dim=128batch_size=64####EncoderModel####encoder_inputs=Input(shape=(maxlen,),name='Encoder-Input')emb_layer=Embedding(num_words,embed_dim,input_length=maxlen,name='Body-Word-Embedding',mask_zero=False)x=emb_layer(encoder_inputs)_,state_h=GRU(latent_dim,return_state=True,name='Encoder-Last-GRU')(x)encoder_model=Model(inputs=encoder_inputs,outputs=state_h,name='编码器模型')seq2seq_encoder_out=encoder_model(encoder_inputs)####DecoderModel####decoder_inputs_before=Input(shape=(None,),name='Decoder-Input-before')#forteacherforcingdec_emb_before=emb_layer(decoder_inputs_before)decoder_gru_before=GRU(latent_dim,return_state=True,return_sequences=True,name='Decoder-GRU-before')decoder_gru_output_before,_=decoder_gru_before(dec_emb_before,initial_state=seq2seq_encoder_out)decoder_dense_before=Dense(num_soft=max,激活名称='Final-Output-Dense-before')decoder_outputs_before=decoder_dense_before(decoder_gru_output_before)decoder_inputs_after=Input(shape=(None,),name='Decoder-Input-after')#forteacherforcingdec_emb_after=emb_layer(decoder_inputs_after)decoder_gru_after=GRU(latent_dim),return_state=True,return_sequences=True,name='Decoder-GRU-after')decoder_gru_output_after,_=decoder_gru_after(dec_emb_after,initial_state=seq2seq_encoder_out)decoder_dense_after=Dense(num_words,activation='softmax',name='Final-Output-Dense-after')decoder_outputs_after=decoder_dense_after(decoder_gru_output_after)####Seq2SeqModel####seq2seq_Model=模型([encoder_inputs,decoder_inputs_before,decoder_inputs_after],(decoder_outputs_before.decoder_outputs_before,decoder_decoder_outputs_after)optimizer=optimizers.Nadam(lr=0.001),loss='sparse_categorical_crossentropy')seq2seq_Model.summary()history=seq2seq_Model.fit([x_skip,x_before,x_after],[np.expand_dims(y_before,-1),np.expand_dims(y_after,-1)],batch_sizebatch_size=batch_size,epochs=10,validation_split=0.12)#Featureextractionheadlines=tokenizer.texts_to_sequences(data['headline'].values)headlines=pad_sequences(headlines,maxlenmaxlen=maxlen)x=encoder_model。预测(标题)#classifierX_train,y_train,X_test,y_test=x[msk],y[msk],x[~msk],y[~msk]lr=LogisticRegression().fit(X_train,y_train)lr.score(x_test,y_test)这次我们取得了74%的准确率,这是迄今为止获得的最高准确率。总结在本文中,我们介绍了三种使用RNN创建句子向量表示的无监督方法,并展示了它们在解决监督任务中的效率。自动编码器的结果比我们的基线模型差一些(这可能是由于使用的数据集相对较小)。Skip-thoughtvectormodel语言模型都是利用上下文来预测句子表征,得到最好的结果。可以提高我们展示的方法性能的可用方法有:调整超参数、训练更多时期、使用预训练嵌入矩阵、改变神经网络架构等。理论上,这些先进的调节工作可能会稍微改变结果.但是,我认为每种预处理方法的基本直觉都可以使用上面共享的示例来实现。原文链接:https://blog.myyellowroad.com/unsupervised-sentence-representation-with-deep-learning-104b90079a93oftheMachine(id:almosthuman2014)”]点此阅读作者更多好文