CBOW (txt 텍스트 소설을 예로 들겠습니다) pytorch 실제 전투

CBOW(파이토치 연습의 예로 txt 텍스트 소설을 사용함)

오늘 블로거가 좋은 실험을 했는데, 많은 친구들이 그로부터 뭔가를 배울 수 있을 것 같아요.

먼저 이 실험과 제가 한 일에 대해 이야기하겠습니다. 이 실험에서 블로거는 txt 파일에서 처음부터 시작하여 이 파일에 있는 중국어 단어를 분할하고 원-핫 인코딩을 수행합니다. 데이터를 처리한 후 또한 구축합니다. cbow 네트워크. 그 후 우리는 자체 모델을 학습시켰고 이를 기반으로 모델에 대한 검증, 즉 우리가 얻은 임베딩 단어 벡터를 통해 특정 단어와 가장 가까운 k 단어를 계산했습니다. 데이터 세트의 품질이 매우 낮은 것으로 나타났지만 검증 후에도 모델은 여전히 ​​일정한 효과를 나타냈습니다.

먼저 데이터 세트 처리 및 모델 교육에 사용할 수 있는 코드를 살펴보겠습니다.


#coding=gbk

import os
import jieba



import torch
from torch import nn, optim
from torch.autograd import Variable
import torch.nn.functional as F

path="E:\\data\\dataz.txt"


def   read_file(path):
    fp=open(path,encoding='utf8')
    text=fp.readlines()
    fp.close()
    return text
    


def cut_words(text):
    dict_index={
    
    }
    index=0
    words_list=[]
    for line in text:
        line=line.replace('"','')
        line=line.replace('“','')
        line=line.replace('”','')
        line=line.replace('。','')
        line=line.replace('\n','')
        line=line.replace(' ','')
        words_cut=line.split(',')
        for i in words_cut:
            words_l=jieba.lcut(i)
            
            for word in words_l:
                if word  not in dict_index.keys():
                    dict_index[word]=index
                    index=index+1
            if  len(words_l)>0:
                    words_list.append(words_l)
                    
                    
                
    return words_list,dict_index
            
        
       

def get_data_corpus(words_list,window_size):
    data_corpus=[]
    for words in  words_list:
        if len(words)<2:
            continue
        else:
           
            for index in range(len(words)):
                l=[]
                target=words[index]
                l.append(target)
                try:
                    l.append(words[index+1])
                    l.append(words[index+2])
                except:
                    pass
                try:
                    l.append(words[index-1])
                    l.append(words[index-2])
                except:
                    pass
                data_corpus.append(l)
    return data_corpus
text=read_file(path)
words_list,dict_index=cut_words(text)
#print(words_list,dict_index)
data_corpus=get_data_corpus(words_list,2)
#print(data_corpus)
class CBOW(nn.Module):

    def __init__(self, vocab_size, embedding_dim):

        super(CBOW, self).__init__()

        self.embeddings = nn.Embedding(vocab_size, embedding_dim)

      #  self.proj = nn.Linear(embedding_dim, vocab_size)

        self.output = nn.Linear(embedding_dim, vocab_size)
        

    def forward(self, inputs):

        embeds = sum(self.embeddings(inputs)).view(1, -1)

       # out = F.relu(self.proj(embeds))

        out = self.output(embeds)

        nll_prob = F.log_softmax(out, dim=-1)

        return nll_prob

length=len(dict_index.keys())

data_final=[]
for words in data_corpus[0:10000]:
    target_vector=torch.zeros(length)
    context_id=[]
    if len(words)==5:
        target_vector[dict_index[words[0]]]=1
        for i in words[1:]:
            context_id.append(dict_index[i])
        data_final.append([target_vector,context_id])
#print(data_final)
epochs=5

model=CBOW(length,100)

loss_function=nn.NLLLoss()
optimizer=optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
losses=[]
for epoch in range(epochs):

    total_loss = 0

    for data in data_final:
        target=data[0]
        context=data[1]

      #  context_vector = make_context_vector(context, word_to_idx).to(device)  # 把训练集的上下文和标签都放到cpu中

        target = torch.tensor(target).type(dtype=torch.long)
        context=torch.tensor(context)
        model.zero_grad()                                                      # 梯度清零

        train_predict = model(context)                                  # 开始前向传播
        # print("train_predict",train_predict[0])
        # print("target",target)
        loss = loss_function(train_predict[0], target)

        loss.backward()                                                        # 反向传播

        optimizer.step()                                                       # 更新参数

        total_loss += loss.item()
    print("loss ",total_loss)
    losses.append(total_loss) 
#保存
torch.save(model,'E:\\data\\cbow.pt')
#读取



os.system("pause")

다음은 특정 단어에 대한 최근 어휘 평가를 수행하는 코드입니다.

#coding=gbk
import os
import jieba



import torch
from torch import nn, optim
from torch.autograd import Variable
import torch.nn.functional as F

path="E:\\data\\dataz.txt"


def   read_file(path):
    fp=open(path,encoding='utf8')
    text=fp.readlines()
    fp.close()
    return text
    


def cut_words(text):
    dict_index={
    
    }
    index=0
    words_list=[]
    for line in text:
        line=line.replace('"','')
        line=line.replace('“','')
        line=line.replace('”','')
        line=line.replace('。','')
        line=line.replace('\n','')
        line=line.replace(' ','')
        words_cut=line.split(',')
        for i in words_cut:
            words_l=jieba.lcut(i)
            
            for word in words_l:
                if word  not in dict_index.keys():
                    dict_index[word]=index
                    index=index+1
            if  len(words_l)>0:
                    words_list.append(words_l)
                    
                    
                
    return words_list,dict_index
            
        
class CBOW(nn.Module):

    def __init__(self, vocab_size, embedding_dim):

        super(CBOW, self).__init__()

        self.embeddings = nn.Embedding(vocab_size, embedding_dim)

      #  self.proj = nn.Linear(embedding_dim, vocab_size)

        self.output = nn.Linear(embedding_dim, vocab_size)
        

    def forward(self, inputs):

        embeds = sum(self.embeddings(inputs)).view(1, -1)

       # out = F.relu(self.proj(embeds))

        out = self.output(embeds)

        nll_prob = F.log_softmax(out, dim=-1)

        return nll_prob

def get_data_corpus(words_list,window_size):
    data_corpus=[]
    for words in  words_list:
        if len(words)<2:
            continue
        else:
           
            for index in range(len(words)):
                l=[]
                target=words[index]
                l.append(target)
                try:
                    l.append(words[index+1])
                    l.append(words[index+2])
                except:
                    pass
                try:
                    l.append(words[index-1])
                    l.append(words[index-2])
                except:
                    pass
                data_corpus.append(l)
    return data_corpus
text=read_file(path)
words_list,dict_index=cut_words(text)
print(dict_index)
path='E:\\data\\cbow.pt'
model = torch.load('E:\\data\\cbow.pt')

print(type(model.state_dict()))  # 查看state_dict所返回的类型,是一个“顺序字典OrderedDict”
 
for param_tensor in model.state_dict(): # 字典的遍历默认是遍历 key,所以param_tensor实际上是键值
    print(param_tensor,'\t',model.state_dict()[param_tensor].size())
    

embedings=model.state_dict()['embeddings.weight']
print(embedings)
print(len(embedings[0]))


# print("萧炎:",dict_index['萧炎'])


dict_values={
    
    }
for key in dict_index.keys():
    dict_values[dict_index[key]]=key
    




def get_most_approch(embedings,target_id,k):
    target_vec=embedings[target_id]
    
    dict_k={
    
    }
    index=0
    for vec in embedings:
        dict_k[index]=float(torch.dot(vec,target_vec))
        index=index+1
    
    sort_z=sorted(dict_k.items(),key=lambda e:e[1],reverse=True
                  ) #排序
    for i in sort_z[0:k]:
        print(dict_values[i[0]])
    
get_most_approch(embedings,dict_index['萧炎'],10)









os.system("pause")

테스트 결과 중 하나를 살펴보세요:
여기에 이미지 설명을 삽입하세요.
위 사진은 Xiao Yan과 관련하여 테스트한 30개의 단어입니다. 위의 단어 중 많은 부분이 사람이 말하는 것이므로 여전히 괜찮다는 것을 알 수 있습니다. Xiao Yan은 사람의 이름입니다. , 둘째, 제자 나란(Nalan)은 샤오옌(Xiao Yan)과 밀접한 관련이 있으며, 이는 이 모델이 일정한 효과가 있음을 보여줍니다.
데이터 세트를 내 리소스에 업로드하고, 코드를 실행하려는 사람들은 데이터 세트를 다운로드할 수 있습니다.

추천

출처blog.csdn.net/weixin_43327597/article/details/133187872