最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用pytorch和torchtext進行文本分類的實例

 更新時間:2020年01月08日 09:21:39   作者:TianHongZXY  
今天小編就為大家分享一篇使用pytorch和torchtext進行文本分類的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

文本分類是NLP領(lǐng)域的較為容易的入門問題,本文記錄我自己在做文本分類任務(wù)以及復(fù)現(xiàn)相關(guān)論文時的基本流程,絕大部分操作都使用了torch和torchtext兩個庫。

1. 文本數(shù)據(jù)預(yù)處理

首先數(shù)據(jù)存儲在三個csv文件中,分別是train.csv,valid.csv,test.csv,第一列存儲的是文本數(shù)據(jù),例如情感分類問題經(jīng)常是用戶的評論review,例如imdb或者amazon數(shù)據(jù)集。第二列是情感極性polarity,N分類問題的話就有N個值,假設(shè)值得范圍是0~N-1。

下面是很常見的文本預(yù)處理流程,英文文本的話不需要分詞,直接按空格split就行了,這里只會主要說說第4點。

1、去除非文本部分

2、分詞

3、去除停用詞

4、對英文單詞進行詞干提取(stemming)和詞型還原(lemmatization)

5、轉(zhuǎn)為小寫

6、特征處理

Bag of Words

Tf-idf

N-gram

Word2vec

詞干提取和詞型還原

from nltk.stem import SnowballStemmer
stemmer = SnowballStemmer("english") # 選擇語言
from nltk.stem import WordNetLemmatizer 
wnl = WordNetLemmatizer()

SnowballStemmer較為激進,轉(zhuǎn)換有可能出現(xiàn)錯誤,這里較為推薦使用WordNetLemmatizer,它一般只在非??隙ǖ那闆r下才進行轉(zhuǎn)換,否則會返回原來的單詞。

stemmer.stem('knives')
# knive
wnl.lemmatize('knives')
# knife

因為我沒有系統(tǒng)學(xué)習(xí)和研究過NLTK的代碼,所以就不多說了,有興趣的可以自己去閱讀NLTK的源碼。

2. 使用torchtext加載文本數(shù)據(jù)

本節(jié)主要是用的模塊是torchtext里的data模塊,處理的數(shù)據(jù)同上一節(jié)所描述。

首先定義一個tokenizer用來處理文本,比如分詞,小寫化,如果你已經(jīng)根據(jù)上一節(jié)的詞干提取和詞型還原的方法處理過文本里的每一個單詞后可以直接分詞就夠了。

tokenize = lambda x: x.split()

或者也可以更保險點,使用spacy庫,不過就肯定更耗費時間了。

import spacy

spacy_en = spacy.load('en')
def tokenizer(text):
 return [toke.text for toke in spacy_en.tokenizer(text)]

然后要定義Field,至于Field是啥,你可以簡單地把它理解為一個能夠加載、預(yù)處理和存儲文本數(shù)據(jù)和標(biāo)簽的對象。我們可以用它根據(jù)訓(xùn)練數(shù)據(jù)來建立詞表,加載預(yù)訓(xùn)練的Glove詞向量等等。

def DataLoader():
 tokenize = lambda x: x.split()
 # 用戶評論,include_lengths設(shè)為True是為了方便之后使用torch的pack_padded_sequence
 REVIEW = data.Field(sequential=True,tokenize=tokenize, include_lengths=True)
 # 情感極性
 POLARITY = data.LabelField(sequential=False, use_vocab=False, dtype = torch.long)
 # 假如train.csv文件并不是只有兩列,比如1、3列是review和polarity,2列是我們不需要的數(shù)據(jù),
 # 那么就要添加一個全是None的元組, fields列表存儲的Field的順序必須和csv文件中每一列的順序?qū)?yīng),
 # 否則review可能就加載到polarity Field里去了
 fields = [('review', REVIEW), (None, None), ('polarity', POLARITY)]
 
 # 加載train,valid,test數(shù)據(jù)
 train_data, valid_data, test_data = data.TabularDataset.splits(
         path = 'amazon',
         train = 'train.csv',
      validation = 'valid.csv',
      test = 'test.csv',
         format = 'csv',
         fields = fields,
         skip_header = False # 是否跳過文件的第一行
 )
 return REVIEW, POLARITY, train_data

加載完數(shù)據(jù)可以開始建詞表。如果本地沒有預(yù)訓(xùn)練的詞向量文件,在運行下面的代碼時會自動下載到當(dāng)前文件夾下的'.vector_cache'文件夾內(nèi),如果本地已經(jīng)下好了,可以用Vectors指定文件名name,路徑cache,還可以使用Glove。

from torchtext.vocab import Vectors, Glove
import torch

REVIEW, POLARITY, train_data = DataLoader()
# vectors = Vectors(name='glove.6B.300d.txt', cache='.vector_cache')
REVIEW.build_vocab(train_data, # 建詞表是用訓(xùn)練集建,不要用驗證集和測試集
     max_size=400000, # 單詞表容量
     vectors='glove.6B.300d', # 還有'glove.840B.300d'已經(jīng)很多可以選
     unk_init=torch.Tensor.normal_ # 初始化train_data中不存在預(yù)訓(xùn)練詞向量詞表中的單詞
)

# print(REVIEW.vocab.freqs.most_common(20)) 數(shù)據(jù)集里最常出現(xiàn)的20個單詞
# print(REVIEW.vocab.itos[:10])  列表 index to word
# print(REVIEW.vocab.stoi)    字典 word to index

接著就是把預(yù)訓(xùn)練詞向量加載到model的embedding weight里去了。

pretrained_embeddings = REVIEW.vocab.vectors
model.embedding.weight.data.copy_(pretrained_embeddings)
UNK_IDX = REVIEW.vocab.stoi[REVIEW.unk_token]
PAD_IDX = REVIEW.vocab.stoi[REVIEW.pad_token]
# 因為預(yù)訓(xùn)練的權(quán)重的unk和pad的詞向量不是在我們的數(shù)據(jù)集語料上訓(xùn)練得到的,所以最好置零
model.embedding.weight.data[UNK_IDX] = torch.zeros(EMBEDDING_DIM)
model.embedding.weight.data[PAD_IDX] = torch.zeros(EMBEDDING_DIM)

然后用torchtext的迭代器來批量加載數(shù)據(jù),torchtext.data里的BucketIterator非常好用,它可以把長度相近的文本數(shù)據(jù)盡量都放到一個batch里,這樣最大程度地減少padding,數(shù)據(jù)就少了很多無意義的0,也減少了矩陣計算量,也許還能對最終準(zhǔn)確度有幫助(誤)?我憑直覺猜的,沒有做實驗對比過,但是至少能加速訓(xùn)練迭代應(yīng)該是沒有疑問的,如果哪天我有錢了買了臺好點的服務(wù)器做完實驗再來補充。

sort_within_batch設(shè)為True的話,一個batch內(nèi)的數(shù)據(jù)就會按sort_key的排列規(guī)則降序排列,sort_key是排列的規(guī)則,這里使用的是review的長度,即每條用戶評論所包含的單詞數(shù)量。

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits(
            (train_data, valid_data, test_data),
            batch_size=32,
            sort_within_batch=True,
            sort_key = lambda x:len(x.review),
            device=torch.device('cpu'))

最后就是加載數(shù)據(jù)喂給模型了。

for batch in train_iterator:
 # 因為REVIEW Field的inclue_lengths為True,所以還會包含一個句子長度的Tensor
 review, review_len = batch.review 
 # review.size = (seq_length, batch_size) , review_len.size = (batch_size, )
 polarity = batch.polarity
 # polarity.size = (batch_size, )
 predictions = model(review, review_lengths)
 loss = criterion(predictions, polarity) # criterion = nn.CrossEntropyLoss()

3. 使用pytorch寫一個LSTM情感分類器

下面是我簡略寫的一個模型,僅供參考

import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils.rnn import pack_padded_sequence
import torch


class LSTM(nn.Module):

 def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim,
     n_layers, bidirectional, dropout, pad_idx):
  super(LSTM, self).__init__()
  self.embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx=pad_idx)
  self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers=n_layers,
       bidirectional=bidirectional, dropout=dropout)
  self.Ws = nn.Parameter(torch.Tensor(hidden_dim, output_dim))
  self.bs = nn.Parameter(torch.zeros((output_dim, )))
  nn.init.uniform_(self.Ws, -0.1, 0.1)
  nn.init.uniform_(self.bs, -0.1, 0.1)
  self.dropout = nn.Dropout(p=0.5)

 def forward(self, x, x_len):
  x = self.embedding(x)
  x = pack_padded_sequence(x, x_len)
  H, (h_n, c_n) = self.lstm(x)
  h_n = self.dropout(h_n)
  h_n = torch.squeeze(h_n)
  res = torch.matmul(h_n, self.Ws) + self.bs
  y = F.softmax(res, dim=1)
  # y.size(batch_size, output_dim)
  return y

訓(xùn)練函數(shù)

def train(model, iterator, optimizer, criterion):
 epoch_loss = 0
 num_sample = 0
 correct = 0

 model.train()
 for batch in iterator:
  optimizer.zero_grad()
  review, review_lengths = batch.review
  polarity = batch.polarity
  predictions = model(review, review_lengths)
  correct += torch.sum(torch.argmax(preds, dim=1) == polarity)
  loss = criterion(predictions, polarity)
  loss.backward()
  epoch_loss += loss.item()
  num_sample += len(batch)
  optimizer.step()

 return epoch_loss / num_sample, correct.float() / num_sample

if __name__ == '__main__':
 for epoch in range(N_EPOCHS):
 train_loss, acc = train(model, train_iter, optimizer, criterion)
 print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {acc* 100:.2f}%')

注意事項和遇到的一些坑

文本情感分類需不需要去除停用詞?

應(yīng)該是不用的,否則acc有可能下降。

data.TabularDataset.splits雖然好用,但是如果你只想加載訓(xùn)練集,這時候如果直接不給validation和test參數(shù)賦值,那么其他代碼和原來一樣,比如這樣

train_data = data.TabularDataset.splits(
         path = '',
         train = 'train.csv',
         format = 'csv',
         fields = fields,
         skip_header = False # 是否跳過文件的第一行
)

那么底下你一定會報錯,因為data.TabularDataset.splits返回的是一個元組,也就是如果是訓(xùn)練驗證測試三個文件都給了函數(shù),就返回(train_data, valid_data, test_data),這時候你用三個變量去接受函數(shù)返回值當(dāng)然沒問題,元組會自動拆包。

當(dāng)只給函數(shù)一個文件train.csv時,函數(shù)返回的是(train_data)而非train_data,因此正確的寫法應(yīng)該如下

train_data = data.TabularDataset.splits(
         path = '',
         train = 'train.csv',
         format = 'csv',
         fields = fields,
         skip_header = False # 是否跳過文件的第一行
)[0] # 注意這里的切片,選擇元組的第一個也是唯一一個元素賦給train_data


同理data.BucketIterator.splits也有相同的問題,它不但返回的是元組,它的參數(shù)datasets要求也是以元組形式,即(train_data, valid_data, test_data)進行賦值,否則在下面的運行中也會出現(xiàn)各種各樣奇怪的問題。

如果你要生成兩個及以上的迭代器,那么沒問題,直接照上面寫就完事了。

如果你只要生成train_iterator,那么正確的寫法應(yīng)該是下面這樣

train_iter = data.BucketIterator(
   train_data,
   batch_size=32,
   sort_key=lambda x:len(x.review),
   sort_within_batch=True,
   shuffle=True # 訓(xùn)練集需要shuffle,但因為驗證測試集不需要
    # 可以生成驗證和測試集的迭代器直接用data.iterator.Iterator類就足夠了
)

出現(xiàn)的問題 x = pack_padded_sequence(x, x_len) 當(dāng)數(shù)據(jù)集有長度為0的句子時, 就會后面報錯

Adagrad效果比Adam好的多

4. 總結(jié)

不僅僅是NLP領(lǐng)域,在各大頂會中,越來越多的學(xué)者選擇使用Pytorch而非TensorFlow,主要原因就是因為它的易用性,torchtext和pytorch搭配起來是非常方便的NLP工具,可以大大縮短文本預(yù)處理,加載數(shù)據(jù)的時間。

我本人之前用過tf 1.x以及keras,最終擁抱了Pytorch,也是因為它與Numpy極其類似的用法,更Pythonic的代碼,清晰的源碼讓我在遇到bug時能一步一步找到問題所在,動態(tài)圖讓人能隨時看到輸出的Tensor的全部信息,這些都是Pytorch的優(yōu)勢。

現(xiàn)在tf 2.0也在不斷改進,有人笑稱tf越來越像pytorch了,其實pytorch也在不斷向tf學(xué)習(xí),在工業(yè)界,tf仍然處于王者地位,不知道未來pytorch能不能在工業(yè)界也與tf平分秋色,甚至更勝一籌呢?

以上這篇使用pytorch和torchtext進行文本分類的實例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python的字符串操作簡單實例

    Python的字符串操作簡單實例

    這篇文章主要介紹了Python的字符串操作簡單實例,字符串有許多種操作方式,本文帶來幾個操作實例,快來一起看看吧
    2023-04-04
  • 教你使用python實現(xiàn)微信每天給女朋友說晚安

    教你使用python實現(xiàn)微信每天給女朋友說晚安

    非常棒的一個python小實戰(zhàn),文章主要教大家如何用python實現(xiàn)微信每天給女朋友說晚安,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 有關(guān)Tensorflow梯度下降常用的優(yōu)化方法分享

    有關(guān)Tensorflow梯度下降常用的優(yōu)化方法分享

    今天小編就為大家分享一篇有關(guān)Tensorflow梯度下降常用的優(yōu)化方法分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Dockerfile構(gòu)建一個Python Flask 鏡像

    Dockerfile構(gòu)建一個Python Flask 鏡像

    這篇文章主要介紹了Dockerfile構(gòu)建一個Python Flask 鏡像,對正在學(xué)習(xí)的你有一定的參考價值,需要的小伙伴可以參考一下
    2022-01-01
  • python進行數(shù)據(jù)預(yù)處理的4個重要步驟

    python進行數(shù)據(jù)預(yù)處理的4個重要步驟

    在數(shù)據(jù)科學(xué)項目中,數(shù)據(jù)預(yù)處理是最重要的事情之一,本文詳細給大家介紹python進行數(shù)據(jù)預(yù)處理的4個重要步驟:拆分訓(xùn)練集和測試集,處理缺失值,處理分類特征和進行標(biāo)準(zhǔn)化處理,需要的朋友可以參考下
    2023-06-06
  • 實現(xiàn)python?namedtuple元類編程

    實現(xiàn)python?namedtuple元類編程

    這篇文章主要為大家介紹了實現(xiàn)python?namedtuple元類編程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • Python爬蟲包BeautifulSoup實例(三)

    Python爬蟲包BeautifulSoup實例(三)

    這篇文章主要為大家詳細介紹了Python爬蟲包BeautifulSoup實例,具有一定的參考價值,感興趣的朋友可以參考一下
    2018-06-06
  • 用Pygal繪制直方圖代碼示例

    用Pygal繪制直方圖代碼示例

    這篇文章主要介紹了用Pygal繪制直方圖代碼示例,具有一定借鑒價值,需要的朋友可以了解下。
    2017-12-12
  • 淺談pytorch中torch.max和F.softmax函數(shù)的維度解釋

    淺談pytorch中torch.max和F.softmax函數(shù)的維度解釋

    這篇文章主要介紹了淺談pytorch中torch.max和F.softmax函數(shù)的維度解釋,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • 用python + openpyxl處理excel2007文檔思路以及心得

    用python + openpyxl處理excel2007文檔思路以及心得

    最近要幫做RA的老姐寫個合并excel工作表的腳本……源數(shù)據(jù)是4000+個excel 工作表,分布在9個xlsm文件里,文件內(nèi)容是中英文混雜的一些數(shù)據(jù),需要從每張表中提取需要的部分,分門別類合并到多個大的表里。
    2014-07-07

最新評論

石城县| 凉城县| 弥渡县| 凤冈县| 泾阳县| 囊谦县| 湾仔区| 湘阴县| 小金县| 五常市| 桃园市| 凤凰县| 进贤县| 西乌| 黄梅县| 阿克陶县| 甘孜县| 温宿县| 海门市| 潮州市| 松江区| 德格县| 成都市| 澄城县| 屏边| 昌黎县| 乌拉特中旗| 徐闻县| 南涧| 逊克县| 介休市| 盘锦市| 宜兰市| 额尔古纳市| 红桥区| 佛教| 南开区| 观塘区| 犍为县| 蕲春县| 莱西市|