要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗“贝壳”~

———————————————————————————

在之前的开篇提到了text2vec,笔者将其定义为R语言文本分析"No.1",她是一个文本分析的生态系统。笔者在学习之后发现开发者简直牛!基于分享精神,将自学笔记记录出来。开篇内容参考:

重磅︱R+NLP:text2vec包——New 文本分析生态系统 No.1(一,简介)

文档可以以多种方式表达,单独词组、n-grams、特征hashing化的方法等。
      一般来说文本分析的步骤有以下三个步骤:
      1、第一步:把内容表达成为文档-词组矩阵(document-term矩阵,DTM)或者词组共现矩阵(term-co-occurrence矩阵,TCM),换言之第一步就是在文档之上创造一个词条地图。
      2、第二步:找个模型在DTM上进行拟合,有LDA、文本分类等
      3、第三步:在验证集上进行验证

本文在此基础上,将一个官方案例予以演示,算得上是翻译他们官方文档。

————————————————————————————————

一、BOW词袋模型

Bag-of-words model (BoW model)最早出现在自然语言处理(Natural Language Processing)和信息检索(Information Retrieval)领域.。该模型忽略掉文本的语法和语序等要素,将其仅仅看作是若干个词汇的集合,文档中每个单词的出现都是独立的。BoW使用一组无序的单词(words)来表达一段文字或一个文档.。近年来,BoW模型被广泛应用于计算机视觉中。

基于文本的BoW模型的一个简单例子如下:

首先给出两个简单的文本文档如下:

John likes to watch movies. Mary likes too.

John also likes to watch football games.

基于上述两个文档中出现的单词,构建如下一个词典 (dictionary):

{"John": 1, "likes": 2,"to": 3, "watch": 4, "movies": 5,"also": 6, "football": 7, "games": 8,"Mary": 9, "too": 10}

上面的词典中包含10个单词, 每个单词有唯一的索引, 那么每个文本我们可以使用一个10维的向量来表示。如下:

[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]

[1, 1,1, 1, 0, 1, 1, 1, 0, 0]

该向量与原来文本中单词出现的顺序没有关系,而是词典中每个单词在文本中出现的频率。

Distributed Representation是一个稠密、低维的实数限量,它的每一维表示词语的一个潜在特征,该特征捕获了有用的句法和语义特征。其特点是将词语的不同句法和语义特征分布到它的每一个维度上去表示。

关于词袋模型的介绍可以看我的另外一篇博客:自然语言处理︱简述四大类文本分析中的“词向量”(文本词特征提取)

BOW算得上是最简单,但效果竟然也还不错的办法。

————————————————————————————————

二、text2vec基于BOW的情感标注

本文选用的是text2vec开发者自带的数据集,有ID、sentiment代表情感正负面、review代表电影简介的内容。

同样,text2vec的数据结构迁入的是data.table,所以效率极高,纵观来看,开发者都很有良心,每个环节都十分注意效率,再次给赞,关于data,table包可以参考我的另外一篇博客:R︱高效数据操作——data.table包(实战心得、dplyr对比、key灵活用法、数据合并)

1、数据准备

library(text2vec)
library(data.table)
data("movie_review")
setDT(movie_review)
setkey(movie_review, id)
set.seed(2016L)
all_ids = movie_review$id
train_ids = sample(all_ids, 4000)
test_ids = setdiff(all_ids, train_ids)
train = movie_review[J(train_ids)]
test = movie_review[J(test_ids)]

同时区分训练集train与测试集test,利用的是sample函数设置,setDT与setkey是data.table包的主要内容,设置关键KEY,后续很多分析都即为有用。

2、文档向量化(Vectorization)

构造的是一个文档-词频矩阵(DTM矩阵),不同文档、不同词发生的次数。这个稀疏矩阵的表达有两种方式:一种就是n-grams(前面提到的BOW)另外一种就是Hashing化(Feature Hashing)。

text2vec构造DTM矩阵,可有点费劲,来看看流程:

(1)设置分词迭代器,itoken;

(2)分词,create_vocabulary,英文里面直接分割即可,中文可就麻烦了,这里中文可不一样,官方案例是英文的,所以还需要自己处理一下。

(3)设置、形成语料文件,vocab_vectorizer

(4)构建DTM矩阵,create_dtm

尼玛,看下来真是烦,这么多步骤。但是,为什么这么多步骤呢?效率...这么做效率极高,笔者在自己写了一些函数才深刻体会到,R语言的文本分析对效率的要求有多高...  哭个...来看看代码:

prep_fun = tolower
tok_fun = word_tokenizer

it_train = itoken(train$review,
             preprocessor = prep_fun,
             tokenizer = tok_fun,
             ids = train$id,
             progressbar = FALSE)
vocab = create_vocabulary(it_train)

其中的itoken中的参数很多,来解读一下,tok_fun代表词语划分成什么程度,是否需要标点等。

tolower代表英文字符通通变成小写。

vectorizer = vocab_vectorizer(vocab)
dtm_train = create_dtm(it_train, vectorizer)

这里细心的同学一定要注意、留意最后生成的文档顺序以及ID是否一一对应,本次案例当然是一一对应,但是在自己操作的过程中,很容易出现,生成的DTM文档顺序发生了改变,你还不知道怎么改变,然后复查可就麻烦大了。

identical(rownames(dtm_train), train$id)

identical是检验两个值是否完全相等的函数,如果相等则会返回TRUE,相关内容参考我的博客:R语言︱集合运算——小而美法则

3、基于logistics的情感标注

监督式的机器学习算法很多,当然选用一个较为经典、解释性比较强的方法,logistics就是这样的办法,不会的戳我的博客:笔记+R︱Logistics建模简述(logit值)

利用的是R语言中的glmnet包。

library(glmnet)
NFOLDS = 4
glmnet_classifier = cv.glmnet(x = dtm_train, y = train[['sentiment']],
                              family = 'binomial',
                              # L1 penalty
                              alpha = 1,
                              # interested in the area under ROC curve
                              type.measure = "auc",
                              # 5-fold cross-validation
                              nfolds = NFOLDS,
                              # high value is less accurate, but has faster training
                              thresh = 1e-3,
                              # again lower number of iterations for faster training
                              maxit = 1e3)

L1正则化惩罚(不会戳我博客:笔记︱范数正则化L0、L1、L2-岭回归&Lasso回归(稀疏与特征工程)),4折交叉验证。最后plot一下可以看到CV图:


      最大AUC值为0.923,这是训练集的AUC,那么来看看验证集的效果怎么样。

it_test = test$review %>%
  prep_fun %>%
  tok_fun %>%
  itoken(ids = test$id,
         # turn off progressbar because it won't look nice in rmd
         progressbar = FALSE)

dtm_test = create_dtm(it_test, vectorizer)

preds = predict(glmnet_classifier, dtm_test, type = 'response')[,1]
glmnet:::auc(test$sentiment, preds)

最终验证集AUC值为0.91667,效果还不错。

————————————————————————————————

三、text2vec基于BOW的情感标注的优化

1、消除低词频单词

一些停用词、一些低频无效词都是文本噪声。所以针对停用词stopword可以在分词步骤create_vocabulary予以处理,譬如:

stop_words = c("i", "me", "my", "myself", "we", "our", "ours", "ourselves", "you", "your", "yours")
vocab = create_vocabulary(it_train, stopwords = stop_words)

针对一些低频词的修剪,可以在分词create_vocabulary步骤之后以及设置、形成语料文件,vocab_vectorizer之前进行处理:

pruned_vocab = prune_vocabulary(vocab,
                                 term_count_min = 10,
                                 doc_proportion_max = 0.5,
                                 doc_proportion_min = 0.001)
vectorizer = vocab_vectorizer(pruned_vocab)

term_count自然就是词频,低于10的都删掉了。

2、增加文字信息量n-gram

之前模型中都是单独分开,现在可以多多考虑2-grams,就在分词步骤进行优化。那么先来看看n-grams是啥?

如果是1-ngrams,有一句话:you need many money

分割成:

   terms terms_counts doc_counts
1: money            1          1
2:  many            1          1
3:  need            1          1
4:   you            1          1

那么2-ngrams呢?

        terms terms_counts doc_counts
1:      money            1          1
2: many_money            1          1
3:       many            1          1
4:  need_many            1          1
5:   you_need            1          1
6:       need            1          1
7:        you            1          1

譬如一些内容就以小组合的形式出现了。不过,最后尝试建模之后,训练集的AUC值为0.9268,跟原来几乎差不多。。。

3、效率优化:feature hashing化

为什么提到这个呢?R语言的文本处理效率本身不高,而且大数据集下,任何处理软件的处理都显得很无力,所以hash化是一个不可避免的趋势。这一趋势,被雅虎广泛使用( Vowpal Wabbit)。hashing化的好处主要有两个:

1、非常快,效率高

2、内存占用很低。

关于哈希化,可参考我的博客:R语言实现︱局部敏感哈希算法(LSH)解决文本机械相似性的问题(一,基本原理)

Hash化主要在第三步,设置、形成语料文件时进行操作,之后操作一样。

h_vectorizer = hash_vectorizer(hash_size = 2 ^ 14, ngram = c(1L, 2L))

验证之后,验证集的AUC为0.903,下降了2%左右,但是换来了最大化效率的提升,物超所值。

4、数据转变优化方法一:标准化

常规的标准化很常见,不懂的戳我博客:R语言︱数据规范化、归一化

一般来说,文本分析中有时候文档长度很长,但是这一指标对最终结果都是无效的,所以需要惩罚一下文档长度。

text2vec中包括了以下两类标准化,L1normalization与L2 normalization,这是图像处理中较为常见的标准化方式,参考来自博客图像处理中的L1-normalize 和L2-normalize

当一幅图像用某种特征表示出来,一般要进行L1-normalize或者是L2-normalize。

假设一幅图像表示为Y=[x1 x2 x3 x4 x5],

L1-normalize的结果为:

L2-normalize的结果为:

通过L1或L2标准化的图像特征往往具有良好的效果,至于那个更好就需要自己试验。

数据转化主要作用在DTM上,所以是第四步之后,而且主要用于惩罚文档,l1(归一化)的效果就是每行相加为1,函数如下:

dtm_train_l1_norm = normalize(dtm_train, "l1")

有以下三种可选方式:l1 l2 none。

5、数据转变优化方法二:TFIDF

      同样也是作用在DTM最后一步步骤,作用过程也有些繁琐:

(1)设置TFIDF编译器tfidf = TfIdf$new();

(2)转换成TFIDF格式fit_transform(dtm_train, tfidf)。

dtm_train = create_dtm(it_train, vectorizer)

tfidf = TfIdf$new()
dtm_train_tfidf = fit_transform(dtm_train, tfidf)
dtm_test_tfidf  = create_dtm(it_test, vectorizer) %>%
  transform(tfidf)

当然从代码的最简化的角度,可以写成下面这样:

dtm_test_tfidf  = create_dtm(it_test, vectorizer) %>%
  transform(tfidf)

最终结果验证集的AUC值为0.905,貌似还降低了。不过,TFIDF对于效率的提升很显著,一般的任务都是会提升的。所以,是个提升精度的好办法。

————————————————————————————————

应用一:在text2vec中灵活的进行数据转化、并建模

从第三章节来看,数据转化一般是形成DTM之后,或者通过fit或者通过fit_transform来进行数据转化。使用起来可以非常灵活,而且已经生成了DTM,你怎么玩都会出结果,这一点有点厉害!!

1、数据转化之后,可以后续直接分析,而且跟之前的内容是具有可比性的。

2、灵活,可以的情况是,训练集没有进行TFIDF,而测试集可以进行TFIDF转化,单独看效果如何

R+NLP︱text2vec包——BOW词袋模型做监督式情感标注案例(二,情感标注)的更多相关文章

  1. R+NLP︱text2vec包——四类文本挖掘相似性指标 RWMD、cosine、Jaccard 、Euclidean (三,相似距离)

    要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 在之前的开篇提到了text2vec ...

  2. 重磅︱R+NLP:text2vec包——New 文本分析生态系统 No.1(一,简介)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 词向量的表示主流的有两种方式,一种当然是耳熟能 ...

  3. NLP入门(一)词袋模型及句子相似度

      本文作为笔者NLP入门系列文章第一篇,以后我们就要步入NLP时代.   本文将会介绍NLP中常见的词袋模型(Bag of Words)以及如何利用词袋模型来计算句子间的相似度(余弦相似度,cosi ...

  4. 机器学习入门-文本数据-构造Tf-idf词袋模型(词频和逆文档频率) 1.TfidfVectorizer(构造tf-idf词袋模型)

    TF-idf模型:TF表示的是词频:即这个词在一篇文档中出现的频率 idf表示的是逆文档频率, 即log(文档的个数/1+出现该词的文档个数)  可以看出出现该词的文档个数越小,表示这个词越稀有,在这 ...

  5. 机器学习入门-文本数据-构造Ngram词袋模型 1.CountVectorizer(ngram_range) 构建Ngram词袋模型

    函数说明: 1 CountVectorizer(ngram_range=(2, 2)) 进行字符串的前后组合,构造出新的词袋标签 参数说明:ngram_range=(2, 2) 表示选用2个词进行前后 ...

  6. 机器学习入门-文本数据-构造词频词袋模型 1.re.sub(进行字符串的替换) 2.nltk.corpus.stopwords.words(获得停用词表) 3.nltk.WordPunctTokenizer(对字符串进行分词操作) 4.np.vectorize(对函数进行向量化) 5. CountVectorizer(构建词频的词袋模型)

    函数说明: 1. re.sub(r'[^a-zA-Z0-9\s]', repl='', sting=string)  用于进行字符串的替换,这里我们用来去除标点符号 参数说明:r'[^a-zA-Z0- ...

  7. NLP基础——词集模型(SOW)和词袋模型(BOW)

    (1)词集模型(Set Of Words): 单词构成的集合,集合自然每个元素都只有一个,也即词集中的每个单词都只有一个. (2)词袋模型(Bag Of Words): 如果一个单词在文档中出现不止一 ...

  8. 第十九节、基于传统图像处理的目标检测与识别(词袋模型BOW+SVM附代码)

    在上一节.我们已经介绍了使用HOG和SVM实现目标检测和识别,这一节我们将介绍使用词袋模型BOW和SVM实现目标检测和识别. 一 词袋介绍 词袋模型(Bag-Of-Word)的概念最初不是针对计算机视 ...

  9. 计算机视觉中的词袋模型(Bow,Bag-of-words)

    计算机视觉中的词袋模型(Bow,Bag-of-words) Bag-of-words 读 'xw20084898的专栏'的blogBag-of-words model in computer visi ...

随机推荐

  1. Firefox使用Poster插件发送post请求

    目的:验证http请求功能正确与否,需要发送post,get请求,则可以使用Poster插件方便简单. 自我总结,有什么改正的地方请指出,感激不尽! 1.安装Poster插件. 点击firefox右上 ...

  2. 使用mongoose和bcrypt实现用户密码加密

    前面的话 最近在做的个人项目中,需要对密码进行加密保存,对该操作的详细步骤记录如下 介绍 关于mongoose已经写过博客就不再赘述,下面主要介绍bcrypt bcrypt是一个由两个外国人根据Blo ...

  3. 分组密码的工作模式--wiki

    密码学中,块密码的工作模式允许使用同一个块密码密钥对多于一块的数据进行加密,并保证其安全性.[1][2] 块密码自身只能加密长度等于密码块长度的单块数据,若要加密变长数据,则数据必须先被划分为一些单独 ...

  4. 福建百度seo和推广,关键词排名优化,网络营销推广培训

    福建百度seo和推广,关键词排名优化,网络营销推广培训 福建百度seo和推广,关键词排名优化,网络营销推广培训,那么如何才能够让自己的文章信息被百度收录呢?只要说自己的文章能够被百度收录,那么你的信息 ...

  5. 使用Dism备份和全新恢复系统

    1.使用WinPE启动,winPE制作可以参考我的另一文章http://www.cnblogs.com/karl-F/p/6934086.html 2.捕获C盘镜像 (1)查看磁盘 在PE提示符:输入 ...

  6. 如何在Python中从零开始实现随机森林

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 决策树可能会受到高度变异的影响,使得结果对所使用的特定测试数据而言变得脆弱. 根据您的测试数据样本构建多个模型(称为套袋)可以减少这种差异,但是 ...

  7. Centos7新功能

    Centos7 单用户模式   centos7里不再有0-6启动级别,而是4个target   graphical.target  多人模式,支持图形和命令行两种登录,对应之前的3,5级别   mul ...

  8. [ZJOI2008]骑士

    [ZJOI2008]骑士 标签: DP 题目链接 题解 把边看成无向的. 其实就是求这个东西的最大独立集. 但是这不是树,怎么求呢? 其实还是一样的求法. 对于每一个连通块.最多有这个联通块的大小数目 ...

  9. mysql之mysql_config_editor

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn mysql_config_editor允许你把登录的身份验证信息存储 ...

  10. Python比较运算符

    判断两个对象之间的关系,和条件选择和循环结合使用的 以下假设变量a为10,变量b为20: 示例1:输入三个互不相等的整数,按照从小到大输出 num01,num02,num03 = eval(input ...