自然语言处理部分,首先就是要分词了,学习一下!
1. jiebaR对字符串进行分析
使用jiebaR的第一步当然是安装jiabaR包并加载咯
安装: install.packages("jiebaR")
加载: library(jiebaR)
三种分词语句的写法:
wk = worker()
#方法1
wk["我希望未来会很好"]
#方法2
wk<="我希望未来会很好" #此处用=的话可不行哟
#方法3
segment("我希望未来会很好",wk)
结果都是一样的,如下
[1] "我" "希望" "未来" "会" "很" "好"
2. jiebaR对txt文件进行分析
当然也可对文本文件进行分词:当前目录下创建文本文件like.txt
1 获取当前工作空间
> getwd()
[1] "C:/Users/lcc/Documents"
2 建立like.txt文件,保存为utf-8,下面有说明为什么
内容如下
新的一学年开始了,结束了大一的骄傲和浮躁之后,桥川、钟白、任逸帆等人顺利进入了大二。肖海洋也通过了大一的考试,如愿以偿没有留级。大一的同窗情谊依旧继续。过了一个假期,大二伊始,旧同学的离开和新同学的加入,让他们之间的关系也发生了微妙变化。顾一心随家人去了美国上学, 毕十三把这份牵挂变成了学习上奋进的动力。转学生许连翘新转入电摄班并貌似带着神秘的任务。原班主任的离开,让原本散漫的电摄班开始团结。
人物的新旧交替,和大二课业的丰富与繁重,2015级电摄班大二的同窗故事更加精彩。这时的他们褪去了大一的青涩,迎来大学中成长速度最快的一年。九个人开启了各自的梦想,并在跌跌撞撞中实现自己的梦想。又是一年大学时光的流逝,九位同窗好友之间的情谊越来越浓。
执行
输入 wk['like.txt']
,此时同等价于 segment('like.txt',wk)
, wk<='like.txt'
返回 [1] "like.segment.2018-01-08_16_13_17.txt"
,即在同目录下生成了分好词的文件,如下:
> library("jiebaR")
> wk['like.txt']
[1] "like.segment.2018-03-18_19_40_52.txt"
Warning message:
In readLines(input.r, n = lines, encoding = encoding) :
读'like.txt'时最后一行未遂
>
有错误,但是工作空间下生成了分词文件
分词文件内容如下:
新 的 一 学年 开始 了 结束 了 大 一 的 骄傲 和 浮躁 之后 桥川 钟 白 任 逸 帆
等 人 顺利 进入 了 大二 肖 海洋 也 通过 了 大 一 的 考试 如愿以偿 没有 留级 大
一 的 同窗 情谊 依旧 继续 过 了 一个 假期 大二 伊始 旧 同学 的 离开 和 新 同学
的 加入 让 他们 之间 的 关系 也 发生 了 微妙 变化 顾 一心 随 家人 去 了 美国
入 电摄 班 并 貌似 带 着 神秘 的 任务 原 班主任 的 离开 让 原本 散漫 的 电 摄班 开始 团结 人物 的 新旧交替 和 大二 课业 的 丰富 与 繁重 2015 级 电 摄班 大
二 的 同窗 故事 更加 精彩 这时 的 他们 褪去 了 大 一 的 青涩 迎来 大学 中 成长
速度 最快 的 一年 九个 人 开启 了 各自 的 梦想 并 在 跌跌撞撞 中 实现 自己 的
梦想 又 是 一年 大学 时光 的 流逝 九位 同窗好友 之间 的 情谊 越来越 浓
问题:In readLines(input.r, n = lines, encoding = encoding) :
原因:我是直接拷贝的数据,不是编码问题,你可以在txt文件的最后一行打个回车再保存就好了
在notepad++中可以看到区别
最后明显的多了一个换行符,再次执行就没事了
> wk['like.txt']
[1] "like.segment.2018-03-18_20_09_10.txt"
>
3. 现在让我们看一下刚刚到底发生了些什么
3.1 分词引擎
在调用worker()函数时,我们实际是在加载jiebaR
库的分词引擎。jiebaR
库提供了7种分词引擎。
混合模型(MixSegment) type="mix"
:是四个分词引擎里面分词效果较好的类,结它合使用最大概率法
和隐式马尔科夫模型
。
最大概率法(MPSegment) type="mp"
:负责根据Trie树
构建有向无环图
和进行动态规划算法
,是分词算法的核心。
隐式马尔科夫模型(HMMSegment) type="hmm"
:是根据基于人民日报
等语料库构建的HMM模型
来进行分词,主要算法思路
是根据(B,E,M,S)四个状态来代表每个字的隐藏状态。 HMM模型由dict/hmm_model.utf8提供。分词算法即viterbi算法。
索引模型(QuerySegment) type="query"
:先使用混合模型
进行切词,再对于切出来的较长的词,枚举句子中所有可能成词的情况,找出词库里存在。标记模型(tag) type="tag"
Simhash模型(simhash) type="keywords"
:对中文文档计算出对应的simhash值。simhash是谷歌用来进行文本去重的算法,现在广泛应用在文本处理中
。
Simhash引擎
先进行分词和关键词提取,后计算Simhash值和海明距离(详情点击)。
关键词模型(keywods) type="simhash"
:关键词提取所使用逆向文件频率(IDF)文本语料库可以切换成自定义语料库的路径,使用方法与分词类似
一般情况下,使用默认引擎(混合模型)就足够了
。
下面让我们仔细研究以下work()函数
worker(type = "mix", dict = DICTPATH, hmm = HMMPATH, user = USERPATH,
idf = IDFPATH, stop_word = STOPPATH, write = T, qmax = 20, topn = 5,
encoding = "UTF-8", detect = T, symbol = F, lines = 1e+05,
output = NULL, bylines = F, user_weight = "max")
各参数的含义如下:
type
, 引擎类型
dict
, 系统词典
hmm
, HMM模型路径
user
, 用户词典
idf,
IDF词典
6.stop_word
, 关键词用停止词库
write
, 是否将文件分词结果写入文件,默认FALSE
qmax
, 最大成词的字符数,默认20个字符
topn
, 关键词数,默认5个
encoding
, 输入文件的编码,默认UTF-8
detect
, 是否编码检查,默认TRUE
symbol,
是否保留符号,默认FALSE
lines
, 每次读取文件的最大行数,用于控制读取文件的长度。大文件则会分次读取。
output
, 输出路径
15.bylines
, 按行输出
user_weight
, 用户权重
4.验证
work()函数的默认配置:
> wk
Worker Type: Jieba Segment
Default Method : mix
Detect Encoding : TRUE
Default Encoding: UTF-8
Keep Symbols : FALSE
Output Path :
Write File : TRUE
By Lines : FALSE
Max Word Length : 20
Max Read Lines : 1e+05
Fixed Model Components:
$dict
[1] "J:/R_install/R-3.4.3/library/jiebaRD/dict/jieba.dict.utf8"
$user
[1] "J:/R_install/R-3.4.3/library/jiebaRD/dict/user.dict.utf8"
$hmm
[1] "J:/R_install/R-3.4.3/library/jiebaRD/dict/hmm_model.utf8"
$stop_word
NULL
$user_weight
[1] "max"
$timestamp
[1] 1521368056
$default $detect $encoding $symbol $output $write $lines $bylines can be reset.
>
5. 自定义用户词典
编写自定义的词典文件,·mydict.utf8·,这个文件放在getwd()
得到的工作目录下
一学年
大一
钟白
任逸帆
肖海洋
然后,在调用worker时设置自定义的用户词典 wk=worker(user="mydict.utf8")
再次对
like.txt`执行分词,得到的结果如下:
> wk=worker(user="mydict.utf8")
> wk['like.txt']
[1] "like.segment.2018-03-18_22_05_55.txt"
>
查看文件
【自定义词典结果】
【默认词典结果】
6.停止词
此外,过滤停止词的本质与自定义词典是一样的啦,只要把停止词的默认文件换成自己的停止词文件就好啦
例如将参数改为: stop_word="stop.txt"
此外此外,还可能需要去除数据字母,可用正则表达式,用stringr包去除空格等
7. 计算词频
jiabaR
包中有自动计算获取词频的函数,freq()
> wk=worker()
> words="那文件怎么办呢???那就需要读取分词后的文件处理一下,再统计词频了"
> freq(segment(words,wk))
char freq
1 词频 1
2 再 1
3 一下 1
4 处理 1
5 那 2
6 了 1
7 需要 1
8 文件 2
9 后 1
10 怎么办 1
11 呢 1
12 统计 1
13 就 1
14 的 1
15 读取 1
16 分词 1
>
那文件怎么办呢???那就需要读取分词后的文件处理一下,再统计词频了
其实也就是一句代码的事情,啊不,两句。以上面like.txt
分词后的文件like_segment.txt
为例(最后要加一个换行)
> wk=worker()
> out=file("like_segment.txt")
> freq(strsplit(readLines(out,encoding="UTF-8")," ")[[1]])
char freq
1 那文件怎么办呢???那就需要读取分词后的文件处理一下,再统计词频了 1
>
注意:freq的参数是向量。此外,统计词频还可以用table()函数
8. 词性标注
词性标注可以使用worker函数的type参数,type默认为mix,仅需将它设置为tag即可
> wk=worker(type="tag")
> words="那文件怎么办呢???那就需要读取分词后的文件处理一下,再统计词频了"
> wk<=words
r n l y r d v v n
"那" "文件" "怎么办" "呢" "那" "就" "需要" "读取" "分词"
f uj n v m d v n ul
"后" "的" "文件" "处理" "一下" "再" "统计" "词频" "了"
>
jiebaR包关于词典词性标记,采用ictclas的标记方法。ICTCLAS 汉语词性标注集。标注及含义:
标注 |
词性 |
标注 |
词性 |
a |
形容词 |
Ag |
形容词素 |
n |
名词 |
Ng |
名词词素 |
nr |
人名 |
m |
数词 |
d |
副词 |
Dg |
副词词素 |
c |
连词 |
e |
叹词 |
nr |
人名 |
ns |
地名 |
t |
时间词 |
nt |
机构团体 |
9. 提取关键字
依旧可以通过改变worker()的type参数即可
> wk=worker(type="keywords",topn=3)
> wk<=words
13.9007 12.3235 11.7035
"词频" "文件" "分词"
> wk=worker(type="keywords",topn=3)
> words="那文件怎么办呢???那就需要读取分词后的文件处理一下,再统计词频了"
> wk<=words
13.9007 12.3235 11.7035
"词频" "文件" "分词"
> wk=worker(type="simhash",topn=3)
> words="那文件怎么办呢???那就需要读取分词后的文件处理一下,再统计词频了"
> wk<=words
$simhash
[1] "294429109308190777"
$keyword
13.9007 12.3235 11.7035
"词频" "文件" "分词"
>
其中,keywords时, wk<=words 等同于 vector_keywords(words,wk) , keywords(words,wk)
simhash与之相似。
此外,文件分词操作与此类似。
10. 其他操作
此外,jiebaR中还有可能会用到的函数:
1、在默认用户词典的基础上,添加新的用户词 new_user_word ,但仅作用于当前分词引擎
> wk=worker()
> new_user_word(wk,"空乏其身","v")
[1] TRUE
> wk<=words
[1] "那" "文件" "怎么办" "呢" "那" "就" "需要" "读取" "分词"
[10] "后" "的" "文件" "处理" "一下" "再" "统计" "词频" "了"
>
2、停用词过滤函数:filter_segment(分词后的向量,过滤词向量)
3、显示词典路径: show_dictpath()
4、分词的快速模式 qseg (quick segmentation) qseg<=text
5、在线jiebaR分词:https://qinwf.shinyapps.io/jiebaR-shiny/
6、get_tuple() 返回分词结果中 n 个连续的字符串组合的频率情况,可以作为自定义词典的参考