詳解文字分類之DeepCNN的理論與實踐
導讀
最近在梳理文字分類的各個神經網路演算法,特地一個來總結下。下面目錄中多通道卷積已經講過了,下面是連結,沒看的可以瞅瞅。我會一個一個的講解各個演算法的理論與實踐。目錄暫定為:
多通道卷積神經網路(multi_channel_CNN)
深度卷積神經網路(deep_CNN)
基於字元的卷積神經網路(Char_CNN)
迴圈與卷積神經網路並用網路(LSTM_CNN)
樹狀LSTM神經網路(Tree-LSTM)
Transformer(目前常用於NMT)
etc..
之後的以後再補充。今天我們該將第二個,深度卷積神經網路(DeepCNN)。
DeepCNN
DeepCNN即是深度卷積神經網路,就是有大於1層的卷積網路,也可以說是多層卷積網路(Multi_Layer_CNN,咳咳,我就是這麼命名滴!)我們來直接上圖,看看具體長得啥樣子:
我大概描述下這個過程,比如sent_len=10,embed_dim=100,也就是輸入的矩陣為(10*100),假設kernel num=n,用了上下padding,kernel size=(3*100),那麼卷積之後輸出的矩陣為(n*10),接著再將該矩陣放入下個卷積中,放之前我們先對這個矩陣做個轉置,你肯定要問為什麼?俺來告訴你我自己的認識,有兩點:
硬性要求:這個矩陣第一個維度為10是句子長度產生的,所以是變數,我們習慣將該維度的大小控制為定量,比如第一個輸入的值就是(sent_len,embed_dim),embed_dim就為定量,不變。所以轉置即可。
理論要求:(n*10)中的n處於的維度的資料表示的是上個數據kernel對這個資料的10個數據第一次計算,第二次計算... 第10次計算,也就可以表示為通過kernel對上個數據的每個詞和它的上下文進行了新的特徵提取。n則表示用n個kernel對上個句子提取了n次。則最終的矩陣為(n*10),我們要轉成和輸入的格式一樣,將第二維度依然放上一個詞的表示。所以轉置即可。
n 可以設定100,200等。
然後對最終的結果進行pooling,cat,然後進過線性層對映到分類上,進過softmax上進行預測輸出即可。
上述僅僅說的是兩層CNN的搭建,當然你可以搭建很多層啦。
實踐
下面看下具體的pytotch程式碼如何實現
類Multi_Layer_CNN的初始化
def __init__(self, opts, vocab, label_vocab): super(Multi_Layer_CNN, self).__init__() random.seed(opts.seed) torch.manual_seed(opts.seed) torch.cuda.manual_seed(opts.seed) self.embed_dim = opts.embed_size self.word_num = vocab.m_size self.pre_embed_path = opts.pre_embed_path self.string2id = vocab.string2id self.embed_uniform_init = opts.embed_uniform_init self.stride = opts.stride self.kernel_size = opts.kernel_size self.kernel_num = opts.kernel_num self.label_num = label_vocab.m_size self.embed_dropout = opts.embed_dropout self.fc_dropout = opts.fc_dropout self.embeddings = nn.Embedding(self.word_num, self.embed_dim) if opts.pre_embed_path != '': embedding = Embedding.load_predtrained_emb_zero(self.pre_embed_path, self.string2id) self.embeddings.weight.data.copy_(embedding) else: nn.init.uniform_(self.embeddings.weight.data, -self.embed_uniform_init, self.embed_uniform_init) # 2 convs self.convs1 = nn.ModuleList( [nn.Conv2d(1, self.embed_dim, (K, self.embed_dim), stride=self.stride, padding=(K // 2, 0)) for K in self.kernel_size]) self.convs2 = nn.ModuleList( [nn.Conv2d(1, self.kernel_num, (K, self.embed_dim), stride=self.stride, padding=(K // 2, 0)) for K in self.kernel_size]) in_fea = len(self.kernel_size)*self.kernel_num self.linear1 = nn.Linear(in_fea, in_fea // 2) self.linear2 = nn.Linear(in_fea // 2, self.label_num) self.embed_dropout = nn.Dropout(self.embed_dropout) self.fc_dropout = nn.Dropout(self.fc_dropout)
資料流動
def forward(self, input): out = self.embeddings(input) out = self.embed_dropout(out)# torch.Size([64, 39, 100]) l = [] out = out.unsqueeze(1)# torch.Size([64, 1, 39, 100]) for conv in self.convs1: l.append(torch.transpose(F.relu(conv(out)).squeeze(3), 1, 2))# torch.Size([64, 39, 100]) out = l l = [] for conv, last_out in zip(self.convs2, out): l.append(F.relu(conv(last_out.unsqueeze(1))).squeeze(3))# torch.Size([64, 100, 39]) out = l l = [] for i in out: l.append(F.max_pool1d(i, kernel_size=i.size(2)).squeeze(2))# torch.Size([64, 100]) out = torch.cat(l, 1)# torch.Size([64, 300]) out = self.fc_dropout(out) out = self.linear1(out) out = self.linear2(F.relu(out)) return out
資料對比
可以看出多層(深層)CNN還是在有提升的。
原文釋出時間為:2018-11-8
原文作者:zenRRan
本文來自雲棲社群合作伙伴“ ofollow,noindex">深度學習自然語言處理 ”,瞭解相關資訊可以關注“ 深度學習自然語言處理 ”。