import numpy as np
import torch
from torch.functional import split
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
"""
filter_list:
Conv2d(1, 3, kernel_size=(2, 4), stride=(1, 1))
1:表示输入channel为1;
3:表示输出channel为3;
kernel_size: 卷积核大小为[2x4];
stride=(1, 1): 步长为1进行滑动
filter_list:
'0':Conv2d(1, 3, kernel_size=(2, 4), stride=(1, 1))
'1':Conv2d(1, 3, kernel_size=(2, 4), stride=(1, 1))
'2':Conv2d(1, 3, kernel_size=(2, 4), stride=(1, 1))
len():3
a.permute(2, 0, 1): 若a维度为 [6, 1, 3],
将a的维度转化为 [3, 6, 1]
"""
class TextCNN(nn.Module):
def __init__(self):
super(TextCNN, self).__init__()
self.num_filters_total = num_filters * len(filter_sizes) # 3 * 3 = 9
self.W = nn.Embedding(vocab_size, embedding_size) # (16, 4)的词表,根据索引得到
self.Weight = nn.Linear(self.num_filters_total,
num_classes,
bias=False) # Weight:[9, 2] 输入9个特征,输出2个特征,二分类
self.Bias = nn.Parameter(torch.ones(
[num_classes])) # 加个偏置,一维长度为2的向量 data:tensor([1., 1.])
self.filter_list = nn.ModuleList([
nn.Conv2d(1, num_filters, (size, embedding_size))
for size in filter_sizes
]) # nn.Conv2d(1, 3, (2, 4))
def forward(self, x):
embedded_chars = self.W(
x) # embedded_chars:[6, 3, 4] 词向量维度为4,输入x为[6, 3]
# print('embedded_chars_size:{}'.format(embedded_chars.size()))
embedded_chars = embedded_chars.unsqueeze(
1) # 在索引为1的地方扩充一个维度,变为[6, 1, 3, 4]
pooled_outputs = []
# 就相当于进行了三个滤波器,均由输入数据进过Conv2d(1, 3, kernel_size=(2, 4), stride=(1, 1))卷积
# 得到了三个卷积后的结果,也就是输入1,输出3的含义, 输入维度:[6, 3] 输出维度:[6, 1, 1, 3]
for i, conv in enumerate(self.filter_list):
# print(i, conv)
h = F.relu(conv(embedded_chars)) # h: torch.Size([6, 3, 2, 1])
# print("h_size:{}".format(h.size()))
mp = nn.MaxPool2d(
(sequence_length - filter_sizes[i] + 1, 1)) #构建一个维度为 2x1的最大池化
pooled = mp(h).permute(0, 3, 2, 1) # mp(h): [6, 3, 1, 1]
# print("pooled_size:{}".format(
# pooled.size())) #pooled_size:torch.Size([6, 1, 1, 3])
pooled_outputs.append(
pooled) # 最终三个卷积后的结果append到pooled_outputs,将三个滤波器卷积后的结果拼接到list中
# print("pooledn_outputs.size:{}, pooled_outputs:{}".format(
# len(pooled_outputs), pooled_outputs))
h_pool = torch.cat(
pooled_outputs,
len(filter_sizes)) # shape: [6, 1, 1 ,9],将三个6113cat成6119
# print("h_pool_size:{}".format(h_pool.size()))
h_pool_flat = torch.reshape(
h_pool, [-1, self.num_filters_total]) # reshape为:[6, 9]维度
# print("h_pool_flat_size:{}".format(h_pool_flat.size()))
model = self.Weight(
h_pool_flat) + self.Bias # 变为 [6, 2] + 长度为2的向量,得到模型的输出
# print('model:{}'.format(model))
return model
"""
x.view(a,b,c) 将维度变为 [a, b, c]
"""
if __name__ == '__main__':
embedding_size = 4
sequence_length = 3
num_classes = 2
filter_sizes = [2, 2, 2] # ****啥作用?
num_filters = 3 # 不是很懂啊
sentences = [
"i love you", "he loves me", "she likes baseball", "i hate you",
"sorry for that", "this is awful"
]
labels = [1, 1, 1, 0, 0, 0]
# word_list = " ".join(sentences).split()
# print('word_list:{}'.format(word_list))
# word_list = list(set(word_list))
# print('word_list_len:{}, word_list:{}'.format(len(word_list), word_list))
# word_dict = {w: i for i, w in enumerate(word_list)}
word_dict = {
w: i
for i, w in enumerate(list(set(' '.join(sentences).split())))
}
vocab_size = len(word_dict)
model = TextCNN() # 先允许TextCNN的__init__()函数
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
inputs = torch.LongTensor([[word_dict[i] for i in sen.split()]
for sen in sentences])
targets = torch.LongTensor([out for out in labels])
# input_ = ([[word_dict[n] for n in sen.split()]
# for sen in sentences]) # input_ :[batch_size, 3] 3为每条数据的长度
# print('input_size:{}, input:{}'.format(
# torch.Tensor(input_).size(), input_))
# inputs = torch.LongTensor(np.asarray(input_))
# print('inputs_size:{}, inputs:{}'.format(
# inputs.size(), inputs)) # inputs: [6, 3] 一批数据6条,每条数据三个单词
# 训练
for epoch in range(5001):
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
if epoch % 1000 == 0:
print("Epoch:", "%04d" % (epoch), 'cost=', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
test_text = 'he likes you'
test = [[word_dict[t] for t in test_text.split()]]
test = torch.LongTensor(test)
# tests = [np.asarray([word_dict[n] for n in test_text.split()])]
# test_batch = torch.LongTensor(tests)
predict = model(test).data.max(1, keepdim=True)[1]
print("predict:{}".format(predict))
# 保存模型
# torch.save(model, './model/TextCNN.pkl')
|