日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

三、自然语言分类

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 三、自然语言分类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1 數據準備
    • 1.1 數據集拆分
    • 1.2 創建詞庫vocabulary
    • 1.3 batch數據,創建Iterator
  • 2 Word Averaging模型
  • 3 RNN模型
  • 4 CNN

三種分類方式:Word Averaging模型、RNN、CNN。

1 數據準備

第一步是準備數據。代碼中用到的類庫有spacy、torchtext。
torchtext中有data.Field用來處理每個文本字段。dataLabelFiled處理標簽字段。

1.1 數據集拆分

將數據集分為訓練集、驗證集和測試集。了解每種數據集的數據量,查看每一條數據的樣子。
每一條句子是一個樣本。

1.2 創建詞庫vocabulary

TEXT.build_vocab(train_data, max_size=25000, vectors="glove.6B.100d", unk_init=torch.Tensor.normal_) LABEL.build_vocab(train_data)

設置詞表大小,用詞向量初始化詞表。

1.3 batch數據,創建Iterator

訓練的時候是一個batch,一個batch訓練的。torchtext會將短句子pad到和最長的句子長度相同。

train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits((train_data, valid_data, test_data), batch_size=BATCH_SIZE,device=device)

數據準備好了,就開始用模型訓練吧。

2 Word Averaging模型

我們首先介紹一個簡單的Word Averaging模型。這個模型非常簡單,我們把每個單詞都通過Embedding層投射成word embedding vector,然后把一句話中的所有word vector做個平均,就是整個句子的vector表示了。
接下來把這個sentence vector傳入一個Linear層,做分類即可。
怎么做平均呢?我們使用avg_pool2d來做average pooling。我們的目標是把sentence length那個維度平均成1,然后保留embedding這個維度。
avg_pool2d的kernel size是 (embedded.shape[1], 1),所以句子長度的那個維度會被壓扁。

import torch.nn as nn import torch.nn.functional as Fclass WordAVGModel(nn.Module):def __init__(self, vocab_size, embedding_dim, output_dim, pad_idx):super().__init__()self.embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx=pad_idx)self.fc = nn.Linear(embedding_dim, output_dim)def forward(self, text):embedded = self.embedding(text) # [sent len, batch size, emb dim]embedded = embedded.permute(1, 0, 2) # [batch size, sent len, emb dim]pooled = F.avg_pool2d(embedded, (embedded.shape[1], 1)).squeeze(1) # [batch size, embedding_dim]return self.fc(pooled)

接下來就是模型訓練、評價。

優化函數:nn.BCEWithLogitsLoss()
優化方法:Adm
評價:損失函數值,準確率。

3 RNN模型

我們使用最后一個hidden state hTh_ThT?來表示整個句子。
然后我們把hTh_ThT?通過一個線性變換f,然后用來預測句子的情感。

class RNN(nn.Module):def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, bidirectional, dropout, pad_idx):super().__init__()self.embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx=pad_idx)self.rnn = nn.LSTM(embedding_dim, hidden_dim, num_layers=n_layers, bidirectional=bidirectional, dropout=dropout)self.fc = nn.Linear(hidden_dim*2, output_dim)self.dropout = nn.Dropout(dropout)def forward(self, text):embedded = self.dropout(self.embedding(text)) #[sent len, batch size, emb dim]output, (hidden, cell) = self.rnn(embedded)#output = [sent len, batch size, hid dim * num directions]#hidden = [num layers * num directions, batch size, hid dim]#cell = [num layers * num directions, batch size, hid dim]#concat the final forward (hidden[-2,:,:]) and backward (hidden[-1,:,:]) hidden layers#and apply dropouthidden = self.dropout(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim=1)) # [batch size, hid dim * num directions]return self.fc(hidden.squeeze(0))

4 CNN

CNN可以把每個局域的特征提出來。在用于句子情感分類的時候,其實是做了一個ngram的特征抽取。
首先做一個embedding,得到每個詞的詞向量,是一個k維的向量。每個詞的詞向量結合到一起,得到一個nxk的矩陣。n是單詞個數。

其次卷積層filter?,F在相當于一個hgram。最后轉化為h個單詞。

w是hxk的。
每一個h單詞的窗口都會被這個filter轉化。c=[c1,c2,...cn?h?1]c=[c_1,c_2,...c_{n-h-1}]c=[c1?,c2?,...cn?h?1?]

上圖中是一個卷積核為(3,embedding_size)的卷積。每次作用于3個單詞,形成3-gram結果。

一般來說會選用多個卷積核:下圖是作用了3個(3,embedding_size)卷積核。也可以使用不同尺寸的卷積核。

第三步,做一個max-over-time pooling。C^=max{c}\widehat{C}=max\{c\}C=max{c}

如果有m個filter,我們會得到z=[C1^,C2^,...Cm^]z=[\widehat{C_1},\widehat{C_2},...\widehat{C_m}]z=[C1??,C2??,...Cm??]

第四步,對z做一個線性變換,得到分類。

class CNN(nn.Module):def __init__(self, vocab_size, embedding_size, output_size, pad_idx, n_filters, filter_sizes, dropout):super(CNN, self).__init__()self.embedding = nn.Embedding(vocab_size, embedding_size, padding_idx=pad_idx)self.convs = nn.ModuleList([nn.Conv2d(in_channels=1, out_channels=n_filters, kernel_size=(fs, embedding_size)) for fs in filter_sizes])self.linear = nn.Linear(len(filter_sizes) * n_filters, output_size)self.dropout = nn.Dropout(dropout)def forward(self, text):# text : [seq_len, batch_size]text = text.permute(1, 0) # [batch_size,seq_len]embed = self.embedding(text) # [batch_size, seq_len, embedding_size]embed = embed.unsqueeze(1) # [batch_size, 1, seq_len, embedding_size]# conved中每一個的形狀是:[batch_size, n_filters, seq_len-filter_sizes[i]+1,embedding_size-embedding_size+1]# 因為kernel_size的第二個維度是embedding_sizeconved = [conv(embed) for conv in self.convs]# conved中每一個的形狀是:[batch_size, n_filters, seq_len-filter_sizes[i]+1]conved = [F.relu(conv).squeeze(3) for conv in conved]# pooled中的每一個形狀是:[batch_size, n_filters, 1]pooled = [F.max_pool1d(conv, conv.shape[2]) for conv in conved]# pooled中的每一個形狀是:[batch_size, n_filters]pooled = [conv.squeeze(2) for conv in pooled]cat = self.dropout(torch.cat(pooled, dim=1)) # [batch_size, len(filter_sizes) * n_filters]return self.linear(cat) # [batch_size,output_size]N_FILTERS = 100 FILTER_SIZES = [3, 4, 5] DROPOUT = 0.5 cnn_model = CNN(VOCAB_SIZE, EMBEDDING_SIZE, OUTPUT_SIZE, PAD_IDX, N_FILTERS, FILTER_SIZES, DROPOUT)

代碼中的卷積核分別為:(3,embedding_size),(4,embedding_size),(5,embedding_size)
每次卷積完成之后,[batch_size, n_filters, seq_len-filter_sizes[i]+1,embedding_size-embedding_size+1],最后一個維度為1。

因為多個卷積之后的形狀不一樣,通過max_pooling層后統一變為[batch_size, n_filters]。這樣就可以將多個卷積的結果拼接在一起,送入全連接層。

總結

以上是生活随笔為你收集整理的三、自然语言分类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。