记intel杯比赛中各种bug与debug【其四】:基于长短时记忆神经网络的中文分词的实现
(标题长一点就能让外行人感觉到高大上)
直接切入主题好了,这个比赛还必须一个神经网络才可以
所以我们结合主题,打算写一个神经网络的中文分词
这里主要写一下数据的收集和处理,网络的设计,代码的编写和模型测试
数据问题
这个模型的数据,我们打算分三类来:
用msr, pku, as, cityu的语料作数据
这些是人工分词的数据,作为数据是最合适的
虽然数据量确实不小(共158999行),但我们有几个另外的想法用已有的多个中文分词工具,对小说、新闻、法律等进行分词,作为数据
很多分词工具的分词结果并不理想,总是有一部分正确,一部分不通
现在把多个分隔作为频率,再设置一个阈值,作为是否分隔的依据
对于我们这个模型来说,语言需要一些日常用语的,和一些正式用语
所以数据直接爬取小说、新闻等即可
这样可以把数据扩大非常多直接拼接词语作为数据
这个一开始是斗机灵来着,想着想着到还是值得一试的呵呵
网络设计
想到中文分词就能想到隐马模型,然而需要神经网络的话,就直接用lstm好了
lstm网络的优点就是对序列的选择性记忆,我们人类分词的时候不也是用一点内存来记忆么
我们还要用字嵌入层,它用于把one-hot向量转为一个多维向量
这些向量之间会有相似度,也符合字之间存在相似度这一设定
网络就简单这样写:
embedding->lstm->linear->linear
简单暴力
代码编写
写过pytorch的话,chainer开发就轻而易举
代码写的不好看,反正没人看,就先贴上来把
咋有种acm选手作风
# network.py
import chainer
from chainer import links
from chainer import functions
from chainer import reporter
path="/home/tanglizi/Code/chainer/segment"
params={
"name": "segment",
"src_path": path+"/train_dataset/src",
"save_path": path+"/saved",
"test_path": path+"/test_dataset",
"train_path": path+"/train_dataset",
# just for test
"batch_size": 100,
"word_cnt": 48,
"epoch": 8,
"snap_epoch": 3,
}
class Network(chainer.Chain):
def __init__(self):
super(Network, self).__init__()
with self.init_scope():
self.embed=links.EmbedID(8000, 512)
self.rnn=links.LSTM(512, 256)
self.linear=links.Linear(256, 64)
self.out=links.Linear(64, 5)
def reset_state(self):
self.rnn.reset_state()
def __call__(self, x):
x=self.embed(x)
x=self.rnn(x.reshape((-1, 512)))
x=functions.relu(self.linear(x))
x=self.out(x)
return x
class Classifier(chainer.Chain):
def __init__(self, predictor):
super(Classifier, self).__init__()
with self.init_scope():
self.predictor=predictor
def __call__(self, x, t):
x=self.predictor(x)
t=t.reshape((params['word_cnt']*params['batch_size']))
loss=functions.softmax_cross_entropy(x, t)
accuracy=functions.accuracy(x, t)
reporter.report({'loss': loss, 'accuracy': accuracy}, self)
return loss, accuracy
# controller.py
# 控制训练和测试的类
from network import Network, Classifier
import pickle, os, random
import thulac
import numpy as np
import chainer
from chainer import functions
from chainer import links
from chainer import training
from chainer.training import extensions
class Controller:
def __init__(self, params):
# dir_path contain data/ and label/
self.params=params
self.map={'.': 0}
def process(self, path):
datapath=path+'/data'
labelpath=path+'/label'
if os.path.exists(path+"/dataset.pkl"):
dataset=pickle.load(open(path+"/dataset.pkl", "rb"))
print("read dataset from .pkl")
return dataset
dataset=[]
for file_step, filename in enumerate(os.listdir(datapath)):
file_data=open(datapath+'/'+filename, "r")
file_label=open(labelpath+'/'+filename, "r")
sentences=file_data.read().split('\n')[:-1]
labels=file_label.read().split('\n')[:-1]
for index, (data_in, label_in) in enumerate(zip(sentences, labels)):
if len(label_in)!=self.params['word_cnt']:
print("warning: data block", len(label_in))
continue
data_in+='.'*(self.params['word_cnt']-len(data_in))
data=[]
for step, (char, sign) in enumerate(zip(data_in, label_in)):
if char not in self.map:
self.map[char]=len(self.map)
data.append([self.map[char], int(sign)])
dataset.append(data)
print("#%04d file '%s', datasize %d*64 (%d)"%(file_step, filename, len(dataset), len(dataset)*64))
random.shuffle(dataset)
pickle.dump(dataset, open(path+"/dataset.pkl", "wb"))
pickle.dump(self.map, open(self.params['save_path']+"/map.pkl", "wb"))
return dataset
def train(self):
dataset={}
dataset['test']=self.process(self.params['test_path'])
dataset['train']=self.process(self.params['train_path'])
batchset=[dataset['train'][step:step+self.params['batch_size']]\
for step in range(0, len(dataset['train']-self.params['batch_size']+1), self.params['batch_size'])]
self.net=Classifier(Network())
self.optim=chainer.optimizers.Adam()
self.optim.setup(self.net)
for epoch in range(self.params['epoch']):
batch={'data':[], 'label':[]}
for step, batch in enumerate(batchset):
batch=np.array(batch, dtype=int)
data=batch[:,:,0]
label=batch[:,:,1]
self.net.predictor.reset_state()
self.net.cleargrads()
loss, accuracy=self.net(data, label)
loss.backward()
self.optim.update()
print("#%08d step(epoch %02d) loss=%.8f accuracy=%.8f"%(step, epoch, loss.data, accuracy.data))
if epoch%2==0:
self.sendmail_try("#%02d epoch loss=%.8f accuracy=%.8f"%(epoch, loss.data, accuracy.data), "126")
self.save()
self.sendmail_try(self.params["name"]+" training done.", "126")
def test(self):
self.net=Network()
self.load()
while True:
sentence=input(">> ")
ifcontinue=False;x=[]
for char in sentence:
if char not in self.map:
print(char, "not in map.")
ifcontinue=True
break
else:
x.append(self.map[char])
if ifcontinue: continue
self.net.reset_state()
pred=self.net(np.array(x, dtype=int))
for x, char in zip(pred.data, sentence):
sign=np.where(x==x.max())[0][0]
print(char, end='')
if sign==2: print("/", end='')
print('')
def save(self):
chainer.serializers.save_npz(self.params['save_path']+'/'+self.params['name']+'.model', self.net.predictor)
chainer.serializers.save_npz(self.params['save_path']+'/'+self.params['name']+'.optim', self.optim)
def load(self):
chainer.serializers.load_npz(self.params['save_path']+'/'+self.params['name']+'.model', self.net)
self.map=pickle.load(open(self.params['save_path']+"/map.pkl", "rb"))
def sendmail_try(self, msg, mtype):
try:
self.sendmail(msg, mtype)
except:
pass
def sendmail(self, msg, mtype):
msg = MIMEText(msg, 'plain', 'utf-8')
smtp=""
if mtype=='163':
smtp="smtp.163.com"
sender_addr="...@163.com"
password="..."
elif mtype=='126':
smtp="smtp.126.com"
sender_addr="...@126.com"
password="..."
server = smtplib.SMTP(smtp, 25)
server.set_debuglevel(1)
server.login(sender_addr, password)
server.sendmail(sender_addr, ["...@126.com"], msg.as_string())
server.quit()
接下来拿去训练即可
模型测试
现在没什么时间了,其他模型等以后补完吧...
- 对第一个模型来说,正确率0.82
看起来还不错,其实结果真的不怎么的
幸好下面的贝叶斯分类器把尊严挽回了,不然又要在这费时间了
记intel杯比赛中各种bug与debug【其四】:基于长短时记忆神经网络的中文分词的实现的更多相关文章
- 记intel杯比赛中各种bug与debug【其一】:安装intel caffe
因为intel杯创新软件比赛过程中,并没有任何记录.现在用一点时间把全过程重演一次用作记录. 学习 pytorch 一段时间后,intel比赛突然不让用 pytoch 了,于是打算转战intel ca ...
- 记intel杯比赛中各种bug与debug【其二】:intel caffe的使用和大坑
放弃使用pytorch,学习caffe 本文仅记录个人观点,不免存在许多错误 Caffe 学习 caffe模型生成需要如下步骤 编写network.prototxt 编写solver.prototxt ...
- 记intel杯比赛中各种bug与debug【其五】:朴素贝叶斯分类器的实现和针对性的优化
咱这个项目最主要的就是这个了 贝叶斯分类器用于做可以统计概率的二元分类 典型的例子就是垃圾邮件过滤 理论基础 对于贝叶斯算法,这里附上两个链接,便于理解: 朴素贝叶斯分类器的应用-阮一峰的网络日志 基 ...
- 记intel杯比赛中各种bug与debug【其三】:intel chainer的安装与使用
现在在训练模型,闲着来写一篇 顺着这篇文章,顺利安装上intel chainer 再次感谢 大黄老鼠 intel chainer 使用 头一次使用chainer,本以为又入了一个大坑,实际尝试感觉非常 ...
- postgres中的中文分词zhparser
postgres中的中文分词zhparser postgres中的中文分词方法 基本查了下网络,postgres的中文分词大概有两种方法: Bamboo zhparser 其中的Bamboo安装和使用 ...
- SQL Server 字段类型 decimal(18,6)小数点前是几位?记一次数据库SP的BUG处理
原文:SQL Server 字段类型 decimal(18,6)小数点前是几位?记一次数据库SP的BUG处理 SQL Server 字段类型 decimal(18,6)小数点前是几位? 不可否认,这是 ...
- 那些盒模型在IE6中的BUG们,工程狮的你可曾遇到过?
HTML5学堂 那些盒模型在IE6中的BUG们,工程狮的你可曾遇到过? IE6已经渐渐的开始退出浏览器的历史舞台.虽然当年IE6作为微软的一款利器击败网景,但之后也因为版本的持续不更新而被火狐和谷歌三 ...
- 转:移动开发中一些bug及解决方案
网页开发要面对各种各样的浏览器,让人很头疼,而移动开发中,你不但要面对浏览器,还要面对各种版本的手机,iOS好一点,而安卓就五花八门了,你可能在开发中也被它们折磨过,或者正在被它们折磨,我在这里说几个 ...
- 写代码的心得,怎么减少编程中的 bug?
遭遇 bug 的时候,理性的程序员会说:这个 bug 能复现吗? 自负型:这不可能,在我这是好好的. 经验型:不应该,以前怎么没问题? 幻想型:可能是数据有问题. 无辜型:我好几个星期都没碰这块代码了 ...
随机推荐
- Kettle的改名由来
不多说,直接上干货! 当时啊,因为很多开源项目到最后都成了无人管的项目,为了避免这种情况的发生,要尽快为Kettle项目构建一个社区.这就意味着,在随后的几年可能需要回答上千封的电子邮件和论坛帖子.幸 ...
- servlet中怎么注入service
在工作中使用到spring的mvc框架,分为controller/service/dao三个层次.偶尔会用到servlet替换掉controller,这就遇到如何在servlet中使用注入到sprin ...
- 【算法】Kruskal算法(解决最小生成树问题) 含代码实现
Kruskal算法和Prim算法一样,都是求最小生成树问题的流行算法. 算法思想: Kruskal算法按照边的权值的顺序从小到大查看一遍,如果不产生圈或者重边,就把当前这条边加入到生成树中. 算法的正 ...
- JavaScript学习——使用JS完成省市二级联动
1.我们希望在注册页面中添加一个字段(籍贯),当用户选择一个具体的省份,在后面的下拉列表中动态加载该省份下所有的城市.显示的效果如下: 2.步骤分析: 第一步:确定事件(onchange)并为其绑定一 ...
- Dapper优秀资料
dapper extensions (predicates) https://www.cnblogs.com/starluck/p/4542370.html
- NOIp2018模拟赛四十一
现在是下午15:36,我已经改完题了...刷新纪录 A题叫B,B题叫A是什么操作??? 我离200只差一个SBFA.jpg 成绩:0+100+10=110 被虐啦...今天九个阿克的Orz.A题是个神 ...
- Linux 文件系统挂载
文件系统挂载简介 磁盘分区和格式化完成后,磁盘分区要想能够使用,就需要挂载,在挂载某个分区前需要先建立一个挂载点 挂载:将新的文件系统关联至当前根文件系统 卸载:将某文件系统与当前根文件系统的关 ...
- Linux快速入门打开你的学习之道
Linux快速入门打开你的学习之道 相信看到这篇文章的你一定是想要学习Linux,或者已经在学习Linux的人了,那我们就可以一起探讨一下,学习Linux如何快速入门呢? 首先,希望大家弄清楚自己为什 ...
- const int *a与int *const a,const int *const a的区别
来源:https://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰 ...
- drupal7 怎样将一个date字段加入上日期插件效果
//这里以created字段为样例 function Hook_form_alter($form,$form_state,$form_id){ $form['created']['#type'] = ...