BPE分词-北邮智科nlp作业1

基于BPE的汉语tokenization

2018211316班 小透明

算法思想:

BPE主要目的是为了数据压缩,算法描述为字符串里频率最常见的一对字符被一个没有在这个字符中出现的字符代替的层层迭代过程

数据结构

变量含义
book列表形式储存训练集文本
vocab列表形式储存词表
pair字典形式存储两词组成新词的频数

函数

函数解释
initvocab初始化词表、book、记录每个字出现的起始位置
init_pairs初始化pair字典
max_pairs寻找pairs中频数最大的子词
update_pairs根据频率最大子词更新pair字典
merge利用训练集得出的词表对测试集进行 划词

伪代码

#初始化词表vocab、字典pairs、文本列表book
vocab=initvocab()
while len(vocab)<=10000:
    #寻找pairs中频数最大的子词
    most_word=max_pair()
    #更新pair字典
    update_pairs()

#利用训练集得出的词表对测试集进行 划词
merge(test,vocab)

优化

  • 问题:在更新book时,起初使用del将两个子词合并新词,但由于列表后单词前移造成巨大时间消耗

    解决:采用标志位flag,表示删除,遇到flag标志后移或前移寻找临接词

  • 问题:更新pair时,要寻找新合成词的邻居,搜索范围过大

    解决:在初始化时,记录每个字出现位置范围用begin、end描述

import collections

flag='$$$FLAG'

def initvocab(filepath, book, vocabfile,begin,end):
    i=0
    f = open(filepath, encoding='utf-8')
    fv = open(vocabfile, "w",encoding='utf-8')
    vocab = []
    vocab.append('\n')
    for lines in f.readlines():

        for word in lines.split(' '):
            word=word.strip(' \r\t\n')

            book.append(word)
            end[word]=i
            if word not in vocab:
                begin[word]=i
                fv.write(word+'\n')
                vocab.append(word)
            i=i+1
    fv.close()
    return vocab






def init_pairs(book,pair):
    preword = ""
    for word in book:
        pair[preword + word] = pair[preword + word] + 1
        preword = word

    print(pair)
    return pair
def max_pairs(pair,vocab,last):

    last=max(pair,key=lambda x: pair[x])

    print(last,pair[last])
    vocab.append(last)
    return last

def islast(book,i,last):
    flag="$$$FLAG"
    if book[i]==flag:
        return 0
    if book[i]==last[0:len(book[i])]:
        j=i+1
        while book[j]==flag and j+1<len(book):
            j=j+1

        if book[i]+book[j]==last:
            return j
    return 0
def update_book(book,last,pair):
    i=begin[last[0]]
    while i<end[last[0]]:


        if (i< len(book)-1 and  islast(book,i,last)!=0 ):
            ni=islast(book,i,last)
            pair[book[i] + book[ni]] = 0
            j=i-1
            k=ni+1
            while(book[j]==flag and j>=0):
                j=j-1
            while(book[k]==flag and k<len(book)):
                k=k+1

            if j>=0:
                pair[book[j] + book[i]] = pair[book[j] + book[i]] -1


            if k<len(book):
                pair[book[ni] + book[k]] = pair[book[ni] + book[k]] - 1
            book[i]=last
            book[ni]=flag


            if j>=0 :
                pair[book[j]+book[i]]=pair[book[j]+book[i]]+1

            if k<len(book):
                pair[book[i] + book[k]] = pair[book[i] + book[k]] + 1

        i=i+1
    return pair









if __name__ == '__main__':

    filepath = 'train_BPE.txt'
    logpath=r'C:\Users\Administrator\Desktop\bpe\log_train1.txt'
    vocabfile=r'C:\Users\Administrator\Desktop\bpe\vocab_train1.txt'
    fl=open(logpath,"w",encoding='utf-8')
    fv = open(vocabfile, "w",encoding='utf-8')
    book=[] #book is list by line of train set
    vocab=[]
    pair = collections.defaultdict(int)
    begin=collections.defaultdict(int)
    end = collections.defaultdict(int)
    i=0
    last=''
    added=''


    vocab=initvocab(filepath,book,vocabfile,begin,end)
    print(len(vocab))
    pair=init_pairs(book,pair)


    while len(vocab)<=10000:

        print(i,':')

        added=max_pairs(pair,vocab,added)
        s=str(i)+":  "+added+'  '+str(pair[added])+'\r\n'
        fl.write(s)
        fv.write(added+'\n')
        pair= update_book(book,added,pair)
        
        i=i+1
    #print(vocab[:])
    fl.close()
    fv.close()









  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值