如何添加新的pub key到远程服务器


在新的机器上使用git提交代码或者ssh登陆远程服务器的时候往往需要远程服务器密码,或者在远程服务器添加ssh的pub key。

那么如何在本地直接将pub key拷贝到远程服务器,从而实现免密登陆呢?

有两种办法:

第一种方法:

#将本地id_rsa.pub复制到远程服务器
scp ~/.ssh/id_rsa.pub ruben@cpp.pub:/tmp/id_rsa.pub
#下面的步骤在服务器上操作
ssh ruben@cpp.pub
cat /tmp/id_rsa.pub >> ~/.ssh/authorized_keys

第二种方法(以我的服务器为例):


ssh-copy-id ruben@cpp.pub

完成以上操作就可以直接在本地免密直接登陆远程主机或者使用git提交代码了。

阅读全文 »


如何搭建自己的GIT服务器


基本上的程序员都会有一个自己github帐号,帐号下都有若干个项目.有些项目适合公开,有些项目不适合公开,比如自己的私人项目或者自己的一些私人文件. 那么如何在自己的机器上或者云服务器上搭建一个自己的私人git服务器呢? 本文将介绍如何搭建一个自己的私人git服务器.

首先要有一个云服务器,或者自己的本地电脑安装好ubuntu系统.

服务器操作:

安装git和openssh

sudo apt-get install git
sudo apt-get install openssh

初始化仓库

cd ~
git init --bare about.git

生成.ssh目录

ssh-keygen
cd ~/.ssh
ls

可以看到如下目录结构

authorized_keys  id_rsa  id_rsa.pub

客户端操作:

生成key

ssh-keygen
cd ~/.ssh
ls

可以看到如下目录结构

authorized_keys  id_rsa  id_rsa.pub

然后执行:

cat ~/.ssh/id_rsa.pub

可以看到输出一段字符类似:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5LdkvYM4+NT3kTcr.......

服务器操作

cd ~
vim ~/.ssh/authorized_keys

将客户端上的这一段字符ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5LdkvYM4+NT3kTcr.......拷贝到authorized_keys文件里,然后保存退出.

客户端操作:

克隆到本地

在客户端执行:

git clone 服务器用户名@ip:/about.git

可以看到输出如下字符(下面是我的操作的输出):

ruben@ruben:~$ git clone root@cpp.pub:about.git
Cloning into 'about'...
warning: You appear to have cloned an empty repository.

总结

到这里就完成了:

  • 1.在服务器建立git仓库
  • 2.在服务器添加客户端的pub key
  • 3.拷贝远程仓库到本地

完成以上步骤就完成了本文的目标,下面就可以对代码或者文件进行版本管理啦~

阅读全文 »


MITIE的简易教程之wordrep


MITIE是在dlib机器学习库之上开发的NLP工具包,支持分布式词嵌入和结构化SVM。提供英语西班牙语德语的预训练语言模型。MITIT核心代码使用C++编写,支持Python,R,Java,C,MATLAB的集成。

安装

MITIT的编译比较简单,按照下面的步骤就可以即可:

#clone 源码
git clone https://github.com/mit-nlp/MITIE.git
cd MITIE
python setup.py install

完成以上工具即可以在代码中import相应的mitit module:

from mitie import *

训练语言模型

执行:

cd MITIE/tools/wordrep
mkdir build
cd build
cmake ..
make

即可得到wordrep可执行文件,目录结构如下:

-MITIE/tools/wordrep/build
 - CMakeCache.txt  
 - CMakeFiles  
 - cmake_install.cmake  
 - dlib_build  
 - Makefile  
 - mitie_build  
 - wordrep

下面就可以使用wordrep训练自己的语言模型了:

cd ~
mkdir temp
cd temp
mv MITIE/tools/wordrep/build/wordrep .
mkdir zh
cp ~/text.txt ./zh
wordrep -e ./zh

上面的操作中,首先新建一个目录temp作为这次训练的工作目录,然后将wordrep拷贝到temp目录下。

然后新建目录zh用来存放训练的语料,语料的格式如下所示(一行一句,分词之后以空格隔开):

你 可 不要 小看 我 
你 的 身高 是 多少
我 只有 二十厘米 高 , 现在 还 在 买 半价票 呢 
你 有 多 高
我 个子 不高 呢 , 只有 二十厘米 , 出门 要 把 我 抱 在 怀里

训练完毕之后的目录结构为:

/temp
 - substring_set.dat
 - top_word_counts.dat
 - total_word_feature_extractor.dat
 - wordrep
 - zh/
 - substrings.txt
 - top_words.txt
 - word_morph_feature_extractor.dat
 - word_vects.dat

得到语言模型之后就可以测试了,下面是测试代码:

from mitie import *

print ("loading Total Word Feature Extractor...")

twfe = total_word_feature_extractor('zh/total_word_feature_extractor.dat')

# Get fingerprint of feature dictionary
print ("Fingerprint of feature dictionary", twfe.fingerprint)
print ()
# Get number of dimensions of feature vectors
print ("Number of dimensions of feature vectors", twfe.num_dimensions)
print ()
# Get number of words in the dictionary
print ("Number of words in the dictionary", twfe.num_words_in_dictionary)
print ()
# Get list of words in the dictionary
words=twfe.get_words_in_dictionary()
print ("First 10 words in dictionary", words[0:200])
print ()
# Get features for one word
feats = twfe.get_feature_vector("我")
print ("First 5 features of word 'home'", feats[0:])
# The total word feature extractor will generate feature vectors for words not
# in its dictionary as well.  It does this by looking at word morphology.  
feats = twfe.get_feature_vector("_word_not_in_dictionary_")
print ("First 5 features of word '_word_not_in_dictionary_'", feats[0:50])

输出为:

Number of dimensions of feature vectors 271
Number of words in the dictionary 2582
.....
...

阅读全文 »


spaCy的简易教程


spaCy是一个NLP工具包用于完成NLP领域的很多任务比如词性标注,命名实体识别,依存句法分析,归一化,停用词,判断是否词语等,支持Unix/Linux,macOS/os X和Windows操作系统,可以通过pip,conda方式安装。

pip:

pip install -U spacy

conda:

conda install -c conda-forge spacy

支持的语言:

NAME LANGUAGE TYPE
en_core_web_sm English Vocabulary, syntax, entities
en_core_web_md English Vocabulary, syntax, entities, vectors
en_core_web_lg English Vocabulary, syntax, entities, vectors
en_vectors_web_lg English Word vectors
de_core_news_sm German Vocabulary, syntax, entities
es_core_news_sm Spanish Vocabulary, syntax, entities
es_core_news_md Spanish Vocabulary, syntax, entities, vectors
pt_core_news_sm Portuguese Vocabulary, syntax, entities
fr_core_news_sm French Vocabulary, syntax, entities
fr_core_news_md French Vocabulary, syntax, entities, vectors
it_core_news_sm Italian Vocabulary, syntax, entities
nl_core_news_sm Dutch Vocabulary, syntax, entities
xx_ent_wiki_sm Multi-language Named entities

语言模型

语言模型的安装:

#命令行
python -m spacy download xx #xx表示上面表格中的的NAME
#pip
pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_md-1.2.0/en_core_web_md-1.2.0.tar.gz
#本地文件
pip install /Users/you/en_core_web_md-1.2.0.tar.gz

安装语言模型之后就可以在代码中使用了:

import spacy
nlp = spacy.load('en')                       # load model with shortcut link "en"
nlp = spacy.load('en_core_web_sm')           # load model package "en_core_web_sm"
nlp = spacy.load('/path/to/en_core_web_sm')  # load package from a directory

doc = nlp(u'This is a sentence.')

安装中如果遇到问题参考链接

用法

词性标注

doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion')

for token in doc:
    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
          token.shape_, token.is_alpha, token.is_stop)

依存树

doc = nlp(u'Autonomous cars shift insurance liability toward manufacturers')
for token in doc:
    print(token.text, token.dep_, token.head.text, token.head.pos_,
          [child for child in token.children])

命名实体识别:

doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion')

for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)

标签化:

for token in doc:
    print(token.text)

阅读全文 »


解决postgresql 9.5安装失败的问题


在低版本的Ubuntu系统中安装postgresql 9.5遇到下面的问题:

E: Unable to locate package postgresql-9.5

原因是因为低版本中只支持到9.3所以需要手动的更新source list。

解决方案为依次运行:

wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main 9.5" >> /etc/apt/sources.list.d/postgresql.list'
sudo apt-get update
sudo apt-get install postgresql-9.5

阅读全文 »


2017年深度学习在NLP领域的进展和趋势


本文翻译的是这篇文章


在过去的很多年里,深度学习架构和算法在某些领域,比如图像识别和语音处理,取得了令人印象深刻的进展。

最初,深度学习架构和算法在NLP领域并没能取得大的进展,但是最近深度学习在普通NLP任务上的取得的结果显示深度学习也能取得显著的效果。命名实体识别、词性标注和情感分析就即是神经网络模型优于传统方法的地方。而机器翻译是所有进展中是最值得纪念的。

从自己训练word2vec到使用预训练模型

词嵌入是深度学习在NLP中最著名的技术了。词嵌入基于分布假设(Harris (1954)),认为相同意义的词分布在相似的上下文中。关于词嵌入的详细介绍可以参考这篇文章

Smiley face

word2vec (Mikolov et al., 2013)和GloVe (Pennington et al., 2014)算法是词嵌入算法的先驱,但是并不被认为是深度学习算法。word2vec是浅层神经网路,GloVe是基于统计的方法。实践证明使用词嵌入在实践中很有效。 最开始的时候,解决NLP问题需要使用词嵌入的时候倾向与自己训练一个领域相关模型。渐渐的,一些基于Wikipedia, Twitter, Google News, web crawls预训练的模型开始得到广泛应用。使用预训练的词嵌入模型可以很方便的集成到自己的深度学习算法中。 今年表明预训练的词嵌入模型依然是NLP中的一个关键难题。Facebook AI实验室的fastText发布了294中语言的预训练向量。fastText能够避免OOV问题,并在小数据集上优于word2vec和GloVe。 spaCy框架集成了词嵌入和深度学习模型,完成诸如NER和依存分析任务,并且允许用户更新模型或者使用自己的模型。 未来,预训练的模型将在生物、文学、经济等特定领域取得好的效果,但是也存在不能很好的调优问题。同时,一些适应性的词嵌入方法出现了。

通用embedding应用于指定领域

导致预训练词嵌入的应用下降的主要问题是预训练语料和最终使用的语料之间的词分布差别。如果没有足够多的语料训练自己i的词嵌入模型,那么使用预训练的词嵌入模型是有好处的。那么如何将通用词嵌入模型应用到指定领域呢?

NLP中这一类问题通常叫做交叉领域或者领域适应技术,跟迁移学习类似。Yang et al今年做过相关有意思的工作,论文通过给定的源领域embedding使用正则化的skip-gram模型用来学习目标领域的embedding。

论文的方法简单但是有效。想象一下,我们知道源领域中单词w的词嵌入向量为$w_s$。为了计算目标领域$w_t$,作者将$w_s$经过一系列转换。基本的,如果单词在两个领域中频繁出现,那么它的含义将不是领域独立。这种情况下,转换的量比较大,所以结果向量在两个领域中趋向于一致。但是如果单词在一个领域中出现的频率比另一个领域高,那么转换的量将小。

这个研究主题没有得到广泛的研究,但是我相信在不久的将来将会得到更多的关注。

情感分析取得的难以置信的效果

历史上很多的发现都是不经意的,比如青霉素、比如X光。今年,Radford et al.在探索字节等级的循环语言模型性能,该模型的目标是预测Amazon中文本中的下一个字符,他们发现已训练模型中的单个神经元能够高效的预测情绪值。是的,没有听错,单个情感神经元能够准确的区分负面和正面的情感。

Smiley face

在知道这个行为之后,作者决定在Stanford Sentiment Treebank模型上测试模型,得到了91.8%的精度,而先前最好的结果是90.2%。这意味着该模型能够使用非监督的方法使用更少的样例数据就可以实现先进的情感分析。

情感神经元表现

既然该模型是基于字符等级,神经元的状态随着文本中的字符改变并能看到神经元在情感检测中的行为表现。

可以看到在遇到单词best之后,神经元的情感状态变得非常积极,而遇到单词horrendous变得消极。

生成情感倾向文本

该模型是生成式模型,所以能够同样的用于生成Amazon评论文本。可以通过简单的覆盖情感神经元的值即可生成有倾向性的文本。

积极情感 消极情感
Best hammock ever! Stays in place and holds its shape. Comfy (I love the deep neon pictures on it), and looks so cute. They didn’t fit either. Straight high sticks at the end. On par with other buds I have. Lesson learned to avoid.
Just what I was looking for. Nice fitted pants, exactly matched seam to color contrast with other pants I own. Highly recommended and also very happy! The package received was blank and has no barcode. A waste of time and money.

查看实例可以打开链接:生成文本实例

本方法使用的是multiplicative LSTM模型,主要的原因就是它比普通的LSTM模型更容易收敛。在Amazon评价语料库上训练使用了4096个单元。

为什么情感倾向判断的准确度高依然未知。读者可以尝试着训练一个自己的模型并做一些实验,作者的训练花了大概一个月时间。

推特與情分析

推特上的與情分析是一个很有力的工具,人们对某个商业品牌的评价,分析营销活动的影响,竞选活动中希拉里和川普在大众中的评价。

Smiley face

SemEval 2017

推特與情分析不仅受到了NLP领域的广大研究者的关注,也受到政治家和社会活动家的关注。因此从2013年开始,SemEval提出了对应的任务-情感分析。 今年,有48支队伍参与这项任务。今年的5个任务为: 1.子任务A:给定一条推文,判断积极、消极、平和三种情感。 2.子任务B:给定一条推文和一个主题,将主题判断为积极或者消极。 3.子任务C:给定一条推文和一个主题,将推文分为:强烈的积极、轻微的积极、平和、轻微的消极、强烈的消极。 4.子任务D:给定关于某个主题的推文,评估这些推文在消极和积极的分布。 5.子任务E:给定关于某个主题的推文,评估这些推文在强烈的积极、轻微的积极、平和、轻微的消极、强烈的消极中的分布。

参赛队伍中有20个队伍使用了CNN或LSTM模型。尽管如此,SVM模型依然流行,有一些队伍结合了神经网络方法或使用了词嵌入特征。

The BB_twtr system

该组工作发布在(Cliche, 2017),英语组中5个子任务排列第一。作者结合了10个CNN和10个biLSTM用来训练不同的超参和不同的预训练策略。在他们的论文中详细的叙述了网络的结构。 为了训练模型,作者使用了人工标注的推文(子任务A标注了49693条)以及没有标注的1亿推文(只是简单的标记了积极和消极)。这些推文都经过了小写、符号化、特殊符号替换链接和表情、统一重复的字母(比如niiice,niiiiiice统一为niice)。 作者使用了word2vec, GloVe and fastText等方法训练词向量,结果表明并没有哪个方法能够取得更明显的效果,因而作者采用了一种投票的策略。

令人激动的抽象摘要系统

自动摘要和自动翻译是NLP中首要的任务,目前主要有2中方法:基于抽取的方法,从原文中抽取最重要的片段;基于抽象的方法,通过生成摘要。之前基于抽取的方法处于主流地位,由于更为简单的缘故。 去年,基于RNN模型在文本生成中取得了不可思议的效果,尤其是在断文本的输入和输出,但是在长文本中却取得很差的结果。Paulus et al提出了一种神经网络模型克服了这个局限性。如下图所示,结果是令人振奋的。 作者使用biLSTM对输入进行编码,然后使用LSTM解码生成输出。他们的主要贡献是提出了内部注意力机制,分别的注意到了输出和生成的输出的连续性,以及新的训练方法:结合了标准监督单词预测和强化学习

内部注意力机制

内部注意力机制的提出是为了避免输出的重复。为了达到这个目标他们在解码的时候生成输出单词之前使用了暂时的注意力查看输入文本的前面部分。这使得模型在生成步骤使用输入的不同部分。模型也能在解码的时候使用之前的隐藏层状态。这两种方法结合使得在生成摘要输出时选择最合适的单词。

强化学习

不同的人会用不同的单词和句子顺序来生成摘要,但两种摘要都可以认为是合理的。因此,一个好的摘要不用严格的按照训练数据集中的摘要。明白了这个,作者避免使用标准的学习型算法,该算法尽量在每一个解码步骤减小与目标摘要的loss,而是使用强化学习策略,这是一种明智的选择。

end-to-end模型的良好结果

模型在CNN/Daily Mail dataset上测试,并获取到了很好质量和可读性。模型进行了预处理:输入文本标签化,全部小写,数字用0代替,一些特殊的实体被移除。

第一次实现完全非监督机器翻译

双语词汇对应,就是将原语言语料库和目标语言语料库中词对应起来组成对,是之前NLP的任务。自动对应双语词汇也能促进别的任务比如信息检索和统计机器翻译。然而这些方法大部分时间都依赖不同种类的资源,一般来说需要的初始化的双语对齐语料库就都不容易建立。 随着词嵌入取得很大的成功,交叉语料的词嵌入出现了,不同于词汇,对齐的是词嵌入空间。Conneau et al. (2018)的方法不依赖具体的资源,但能取得比有监督的方法更好的效果。 作者的方法是使用单语语料库进行训练各自的词嵌入模型,然后学习两种向量空间之间的映射,就像这种转换使得它们在公共空间内相互靠近。他们使用fastText基于Wikipedia训练非监督的词向量。下面的图片说明了训练的过程:

Smiley face

X代表的是英语,Y代表的是意大利语。 首先他们使用对抗学习的方法学习到转换矩阵W用来执行第一次语料对齐。他们训练了一个生成式对抗网络(GAN),Goodfellow et al. (2014),如果不熟悉GAN,可以参考这篇博文

Smiley face

一些优秀的框架和工具包

AllenNLP

AllenNLP用Pytorch实现的,用于完成机器阅读理解,文本蕴涵,语义角色标注,指代消解,命名实体识别等任务。

ParlAI

ParlAI是一个用于研究对话的开源软件平台,使用python实现,用于训练和测试对话模型,提供多种数据集和模型,比如记忆模型,seq2seq和LSTMs

OpenNMT

OpenNMT实现了seq2seq模型,用于完成机器翻译,摘要,图像文字生成和语音识别。

总结

NLP中采用深度学习的方法越来越多,下面显示的是各会议中NLP采用深度学习方法的论文占比(会议包括ACL, EMNLP, EACL and NAACL)。 然而,端到端学习仅仅开始。现在依然还在处理经典的NLP任务并为之整理数据,比如清洗,标签化,一些实体的统一(链接,数字,邮箱地址等)。我们使用通用的词嵌入模型,副作用就是没有抓住特定领域短语的重要性,并且通用词嵌入模型在多语言表示表现效果不尽如人意。

更多资料

更多的关于深度学习在NLP领域的研究参考Recent Trends in Deep Learning Based Natural Language Processing by Young et al. (2017)。

From Characters to Understanding Natural Language (C2NLU): Robust End-to-End Deep Learning for NLP by Blunsom et al. (2017)讨论的是使用字母作为深度学习模型的输入,而不是采用语言相关的符号,的好处和挑战。

模型之间的比较参考comparative study of CNN and RNN for NLP, by Yin et al. (2017)

GAN的介绍可以参考这篇。

关于词嵌入的介绍可以参考这篇文章

关于词嵌入2017年的发展参考About Word embeddings in 2017: Trends and future directions

参考文献

From Characters to Understanding Natural Language (C2NLU): Robust End-to-End Deep Learning for NLP Phil Blunsom, Kyunghyun Cho, Chris Dyer and Hinrich Schütze (2017)

BB_twtr at SemEval-2017 Task 4: Twitter Sentiment Analysis with CNNs and LSTMs Mathieu Cliche (2017)

Word Translation without Parallel Data Alexis Conneau, Guillaume Lample, Marc’Aurelio Ranzato, Ludovic Denoyer, Hervé Jégou (2018)

Generative adversarial nets Ian Goodfellow, Jean Pouget-Abadie, Mehdi Mirza, Bing Xu, David Warde-Farley, Sherjil Ozair, Aaron Courville and Yoshua Bengio (2014)

Distributional structure Zellig Harris (1954)

OpenNMT: Open-source toolkit for neural machine translation Guillaume Klein, Yoon Kim, Yuntian Deng, Jean Senellart and Alexander M Rush. (2017)

Multiplicative lstm for sequence modelling Ben Krause, Liang Lu, Iain Murray and Steve Renals (2016)

Parlai: A dialog research software platform Alexander H Miller, Will Feng, Adam Fisch, Jiasen Lu, Dhruv Batra, Antoine Bordes, Devi Parikh and Jason Weston (2017)

Linguistic Regularities in Continuous Space Word Representations Tomas Mikolov, Scott Wen-tau Yih and Geoffrey Zweig (2013)

Glove: Global vectors for word representation Jeffrey Pennington, Richard Socher and Christopher D. Manning (2014)

Learning to Generate Reviews and Discovering Sentiment Alec Radford, Rafal Jozefowicz and Ilya Sutskever (2017)

A Simple Regularization-based Algorithm for Learning Cross-Domain Word Embeddings Wei Yang, Wei Lu, Vincent Zheng (2017)

Comparative study of CNN and RNN for Natural Language Processing Wenpeng Yin, Katharina Kann, Mo Yu and Hinrich Schütze (2017)

Recent Trends in Deep Learning Based Natural Language Processing Tom Younga, Devamanyu Hazarikab, Soujanya Poriac and Erik Cambriad (2017)

阅读全文 »


意图分类是怎么实现的


如何进行意图分析

之前开始做语义理解的时候,笔者采用的是比较粗暴的方法进行匹配。随着语料的积累,语料库的规模变得越来越大,匹配的效率也随着越来越低,对语料进行意图分类的想法也就随着产生。

当用户输入之后,系统首先对输入进行意图分类,然后对分类下的语料进行匹配,从而减轻计算量,提高系统的匹配效率。

本文只是简单的阐述一下意图分析的典型思路和方法,并实现一个基本的意图分类器,而无意系统的探究意图分类。更详细的探讨后文再进行。

本文按照如下流程进行叙述:

  • 数据准备
  • 特征提取
  • 模型准备
  • 训练模型
  • 使用模型

数据准备

假设有3个场景:吃饭、打招呼、再见。那么三个场景下会有什么样的对话呢? 比如:

  • 今天这个菜真好吃!
  • 嗨!今天天气不错!
  • 今天很开心,明天见!

很明显,人眼一看就能看出对应的句子应该是哪个类别了:

  • 今天这个菜真好吃! ->吃饭
  • 嗨!今天天气不错! ->打招呼
  • 今天很开心,明天见! ->再见

到这里,我们模型需要的数据就有了。可以很清晰的写出下面的代码:

list_sen=['今天这个菜真好吃!','嗨!今天天气不错!','今天很开心,明天见!']

需要的数据就有了,下一步是提取特征。

特征提取

特征的提取是为了方便进行分类计算,每一个特征都具备一定的权重,表明它的权值。通过特征的权值,就能够确定句子属于哪一个类别。这里我们将每一个字作为一个特征,1/(字出现的总次数)作为权值。 首先构造一个字典,key为字,value为频率:

dict_voc=dict()
for s in list_sen:
    for w in s:
        if w in dict_voc.keys():
            dict_voc[w]+=1
        else:
            dict_voc[w]=1

输出为:

{'这': 1.0, '嗨': 1.0, '好': 1.0, '气': 1.0, '真': 1.0, '错': 1.0, '不': 1.0, '个': 1.0, '心': 1.0, '天': 0.2, '菜': 1.0, '今': 0.3333333333333333, ',': 1.0, '!': 0.25, '吃': 1.0, '明': 1.0, '见': 1.0, '很': 1.0, '开': 1.0}

到这里字典构造完毕,下一步就是构造类别的特征了。 前面说了,我们把每一个类别下的每一个字作为特征,代码也就可以写出来了。

features_one=dict()#吃饭  {字:频率}
features_two=dict()#打招呼
features_three=dict()#再见
for w in list_sen[0]:
    if w in features_one.keys():
        features_one[w]+=1
    else:
        features_one[w]=1
for w in list_sen[1]:
    if w in features_two.keys():
        features_two[w]+=1
    else:
        features_two[w]=1
for w in list_sen[2]:
    if w in features_three.keys():
        features_three[w]+=1
    else:
        features_three[w]=1
print(features_one)
print(features_two)
print(features_three)

#{'好': 1, '天': 1, '真': 1, '吃': 1, '!': 1, '菜': 1, '今': 1, '个': 1, '这': 1}
#{'不': 1, '!': 2, '气': 1, '嗨': 1, '错': 1, '今': 1, '天': 2}
#{'明': 1, '心': 1, '开': 1, '见': 1, ',': 1, '很': 1, '今': 1, '天': 2, '!': 1}

到这里特征的提取已经完成

模型准备

模型准备需要的是建立分类模型。这里我们通过给每一个特征赋予一个得分,然后将句子中每一个字的特征得分进行相加,然后就可以得到句子在某一个类别下特征的总得分,从而能够对句子进行分类。

比方说:今天的工作就到这里吧,大家早点回去,明天再继续吧。 这句话在每一个类别下的得分为:

特征命中:今、天、这、天
类别:吃饭
得分:4

特征命中:今、天、天
类别:打招呼
得分:3

特征命中:今、天、明、天、,、,
类别:再见
得分:6

这里,我们假设每一个字的权重为1,。显然,得分6最高,所属的类别应该是:再见。 到这里,我们所需要的模型就已经建立起来了。

训练模型

上一节有一个问题,比如今天在所有的类别都出现了,拜拜只出现在了再见类别,菜也只出现在了吃饭类别。这是不是意味这每一个特征应该具备不同的权重呢?或者说有些字的辨识度应该更高,有些字的辨识度应该更低呢?

是的,我们在这里通过1/(字出现的总次数)来对字的特征得分进行加权。

特征命中:今(0.3)、天(0.2)、这(1)、天(0.2)
类别:吃饭
得分:1.73

特征命中:今(0.3)、天(0.2)、天(0.2)
类别:打招呼
得分:1.13

特征命中:今(0.3)、天(0.2)、明(1.0)、天(0.2)、,(1.0)、,(1.0)
类别:再见
得分:4.13

结果还是属于类别再见。

有了前面的叙述,可以很方便的进行编码实现:

sen='今天的工作就到这里吧,大家早点回去,明天再继续吧。'
score1=0.0
score2=0.0
score3=0.0
print('class1:')
for w in sen:
    if w in features_one:
        print('word:',w,features_one[w],dict_voc[w])
        score1+=features_one[w]*dict_voc[w]
print('score1:',score1)
print('---------------------')
print('class2:')
for w in sen:
    if w in features_two:
        print('word', w,features_two[w],dict_voc[w])
        score2+=features_two[w]*dict_voc[w]
print('score2:',score2)
print('---------------------')
print('class3:')
for w in sen:
    if w in features_three:
        print('word', w,features_three[w],dict_voc[w])
        score3+=features_three[w]*dict_voc[w]
print('score3:',score3)
print('---------------------')

输出如下:

class1:
word: 今 1 0.3333333333333333
word: 天 1 0.2
word: 这 1 1.0
word: 天 1 0.2
score1: 1.7333333333333332
---------------------
class2:
word 今 1 0.3333333333333333
word 天 2 0.2
word 天 2 0.2
score2: 1.1333333333333333
---------------------
class3:
word 今 1 0.3333333333333333
word 天 2 0.2
word , 1 1.0
word , 1 1.0
word 明 1 1.0
word 天 2 0.2
score3: 4.133333333333334
---------------------

总结

以上就完成了意图分类模型的建立。本文只是对意图分类进行了简单的探讨,实际上的意图分类并不是这么简单,当然,这就是后话了。

阅读全文 »


2.Detect Language with MLP


import torch
import torch.nn as nn
import torch.autograd as autograd
import torch.functional as F

data = [("我 的 家 乡 在 哪 里".split(), "CHINESE"),
        ("Give it to me".split(), "ENGLISH"),
        ("今 天 天 气 怎 么 样".split(), "CHINESE"),
        ("No it is not a good idea to get lost at sea".split(), "ENGLISH")]

test_data = [("天 气 在 哪 里".split(), "CHINESE"),
             ("it is lost on me".split(), "ENGLISH")]
word2index={}
for sen,_ in data+test_data:
    for word in sen:
        if word not in word2index:
            word2index[word]=len(word2index)
print(word2index)
VOCAB_SIZE=len(word2index)
NUM_CLASSES=2
label2index={'CHINESE':0,'ENGLISH':1}

class BoWClassifier(torch.nn.Module):
    def __init__(self,num_labels,vocab_size):
        super(BoWClassifier,self).__init__()
        self.linear=nn.Linear(vocab_size,num_labels)
        self.softmax=nn.Softmax()
    def forward(self,bow_vec):
        return self.softmax(self.linear(bow_vec))
def make_bow_vector(sentence,word2index):
    vec=torch.zeros(len(word2index))
    for word in sentence:
        vec[word2index[word]]+=1
    return vec.view(1,-1)
def make_target(label,label2index):
    return torch.LongTensor([label2index[label]])

model=BoWClassifier(NUM_CLASSES,VOCAB_SIZE)

# for param in model.parameters():
#     print(param)
log_prob=model(autograd.Variable(make_bow_vector(data[0][0],word2index)))
print(log_prob)

loss_function=nn.NLLLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.1)

for epoch in range(100):
    for instance,label in data:
        model.zero_grad()
        bow_vec=autograd.Variable(make_bow_vector(instance,word2index))
        target=autograd.Variable(make_target(label,label2index))
        # print(target)
        log_prob=model(bow_vec)
        # print(log_prob)
        loss=loss_function(log_prob,target)
        loss.backward()
        optimizer.step()
for instance,label in test_data:
    bow_vec=autograd.Variable(make_bow_vector(instance,word2index))
    log_prob=model(bow_vec)
#     print(log_prob)
print(model(autograd.Variable(make_bow_vector(['Give','good','good','good','good'],word2index))))

阅读全文 »