用R语言实现ngram算法

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹,分析师/程序员/Quant: R,Java,Nodejs
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-text-ngram/

前言

大语言模型的文字表达能力,让我们所惊叹算法的魅力。语言能力并不是AI与生俱来的,而且通过底层的各种算法像拼接积木似的组装出来的。我们需要有一个高质量的预料库,然后通过模型训练,你也能拥有文字表达能力。

ngram就给了我们,让惊叹变成现实的这种能力。

目录

  1. ngram算法介绍
  2. 用R语言实现ngram
  3. 生成式算法:用ngram生成一段文字

1. ngram算法介绍

n-gram是一种基于统计语言模型的算法,它的基本思想是将文本里面的内容按照字节进行大小为N的滑动窗口操作,形成了长度是N的字节片段序列。N就是将句子做切割,N个单词为一组。每一个字节片段称为gram,对所有gram的出现频度进行统计,并且按照事先设定好的阈值进行过滤,形成关键gram列表,也就是这个文本的向量特征空间,列表中的每一种gram就是一个特征向量维度。

如:A B A C A B B,可以切分为


P(A B A C A B B) = P(A)*P(B|A)*P(A|A,B)*P(C|A,B,A)…*P(B|A B A C A B)

为了简化问题,我们可以假设当前的字出现只跟前一个字有关,这样就形成了二元的模型。


P(A B A C A B B) = P(A)*P(B|A)*P(A|B)*…*P(B|B)

ngram模型基于这样一种假设,第N个词的出现只与前面N-1个词相关,而与其它任何词都不相关,整句的概率就是各个词出现概率的乘积。这些概率可以通过直接从语料中统计N个词同时出现的次数得到。常用的,一元为unigram,是二元的bi-gram,三元的tri-gram。

  • 一元表示:P(A B A C A B B) = P(A)*P(B)*P(A)*P(C)*P(A)*P(B)*P(B)
  • 二元表示:P(A B A C A B B) = P(A)*P(B|A)*P(A|A)*P(C|A)…*P(B|B)
  • 三元表示:P(A B A C A B B) = P(A)*P(B|A)*P(A|A,B)*P(C|B,A)…*P(B|A,B)

当N值增大时:对单词的约束性更高,具有更高的辨识力,复杂度也随之增大。当N值减小时:词文本出现的次数概率更可靠,统计结果更可靠,但对词文本的约束性减小

为了考虑字词在开头和结尾的位置,可以在文本中加入 start 的 token 和 end 的 token。


P(A B A C A B B) = P(A|<start>)*P(B|A)*P(A|B)*…*P(B|B)*P(<end>|B)

N-gram 的使用方法:

  1. 文本预处理:
    首先,对原始文本进行分词、去除停用词、词干提取等预处理操作,以便得到适合进行N-gram 统计的词序列。
  2. 生成N-grams:
    根据设定的N 值,将预处理后的词序列拆分成若干个N-gram。
  3. 统计频率:
    统计每个N-gram 在文本中出现的次数,并计算其频率。
  4. 构建语言模型:
    利用统计得到的N-gram 频率信息,构建一个语言模型,用于预测下一个词的概率。
  5. 使用语言模型:
    在实际应用中,可以使用构建好的语言模型来预测下一个词的出现概率,从而实现诸如文本生成、语音识别、机器翻译等任务。

2. 用R语言实现ngram

ngram是一个 R 包,用于构建 n-gram(即“分词”),以及根据给定文本输入的 n-gram 结构生成新文本(即“胡言乱语”)。该包可用于进行严肃的分析,或创建说些有趣话语的“机器人”。ngram包旨在以极快的速度对已标记的语料库进行标记化、汇总和汇总。由于其架构设计,我们还能够处理海量文本,并且性能扩展性非常好。基准测试和示例用法可在软件包简介中找到。

ngram包安装和加载


# 安装
> install.packages("ngram")

# 加载
> library(ngram)

创建文本变量x


# 创建变量
> x <- "A B A C A B B"

# 查看字符串属性
> string.summary(x)
Chars:       13
Letters:     7
Whitespace:  6
Punctuation: 0
Digits:      0
Words:       7
Sentences:   0
Lines:       1 
Wordlens:    0 7 
             9 1 
Senlens:     0 
             10 
Syllens:     0 3 
             9 1 

进行ngram二元分词n=2,并预测下一个出现的词。


# ngram二元分词
> ng <- ngram (x , n =2)
> ng
An ngram object with 5 2-grams 

查看ngram的分词预测,可以设置output=”full”时是打印所有的结果。使用output=”truncated”,只会显示前 5 个 n-gram。


# 查看分词结果
> print (ng , output ="full")
C A | 1 
B {1} | 

B A | 1 
C {1} | 

B B | 1 
NULL {1} | 

A C | 1 
A {1} | 

A B | 2 
B {1} | A {1} | 

我们可以看到每个 3-gram 及其下一个可能的 “词”,以及每个词在给定 n-gram 之后的出现频率。

  • 第一组C A 的下一个可能词是 B,因为在输入的字符串中,序列 C A 的后面只有 B。
  • 第五组A B 的后面有一次 A 和一次 B。
  • 第三组B B 是终结符,即后面什么也没有。

生成短语表,文本的 ngram 表示一旦生成,就可以非常简单地获取一些有趣的摘要信息。函数 get.phrasetable() 生成了一个 n-grams 表,以及它们在文本中的频率和比例。


> get.phrasetable ( ng )
  ngrams freq      prop
1   A B     2 0.3333333
2   C A     1 0.1666667
3   B A     1 0.1666667
4   B B     1 0.1666667
5   A C     1 0.1666667

AB,出现过2次,概率是0.33。其他组合,都只出现过一次,概率是0.16.

再分别生成n=1和n=3的短语表。


> get.phrasetable ( ngram (x , n =1) )
  ngrams freq      prop
1     A     3 0.4285714
2     B     3 0.4285714
3     C     1 0.1428571

> get.phrasetable ( ngram (x , n =3) )
  ngrams freq prop
1 C A B     1  0.2
2 A B A     1  0.2
3 A B B     1  0.2
4 B A C     1  0.2
5 A C A     1  0.2

另外还有2个工具函数


# 提取组合
> get.ngrams(ng)
[1] "C A" "B A" "B B" "A C" "A B"

# 查看原始的数据
> get.string(ng)
[1] "A B A C A B B"

使用babble()函数,通过ngrams来生成与输入字符串具有相同统计属性的新字符串。

随机生成3组字符。


> babble (ng , 10)
[1] "A C A B B B B A B B "

> babble (ng , 10)
[1] "C A B B C A B B A C "

> babble (ng , 20)
[1] "B A C A B B B A C A B B A B B B A C A B "

我们也可以指定种子生成相同的内容。


> babble (ng , 10 , seed =10)
[1] "A C A B B B B A B B "

> babble (ng , 10 , seed =10)
[1] "A C A B B B B A B B "

3. 生成式算法:用ngram生成一段文字

通过babble(),是不是看到生成式大模型的影子了,为什么模型能生成出来说法通顺的文字呢。

我们多给一些语言描述,让ngram进行算法识别。

生成语言文字。


x<-c(
+ "how are you",
+ "I like you",
+ "I love you",
+ "I think you're the best for me",
+ "We re good friends",
+ "We're all good"
+ )

# 拼接成一个句子
> x<-str_c(x,collapse = " ")
> x
[1] "how are you I like you I love you I think you're the best for me We re good friends We're all good"

构建ngram模型


> ng <- ngram (x , n=2)
> ng
An ngram object with 20 2-grams 

# 查看语言序列
> print (ng , output ="truncated")
the best | 1 
for {1} | 

for me | 1 
We {1} | 

friends We're | 1 
all {1} | 

are you | 1 
I {1} | 

I think | 1 
you're {1} | 

[[ ... results truncated ... ]]

查看短语概率表


> get.phrasetable ( ng )
           ngrams freq       prop
1          you I     3 0.13636364
2       the best     1 0.04545455
3         for me     1 0.04545455
4  friends We're     1 0.04545455
5        are you     1 0.04545455
6        I think     1 0.04545455
7   good friends     1 0.04545455
8         I like     1 0.04545455
9   think you're     1 0.04545455
10      like you     1 0.04545455
11      all good     1 0.04545455
12        I love     1 0.04545455
13         me We     1 0.04545455
14      love you     1 0.04545455
15         We re     1 0.04545455
16       how are     1 0.04545455
17       re good     1 0.04545455
18    you're the     1 0.04545455
19      best for     1 0.04545455
20     We're all     1 0.04545455

接下来就是神奇的时刻,自动生成10个短语。


> babble (ng , 10)
[1] "me We re good friends We're all good I love "

> babble (ng , 10)
[1] "for me We re good friends We're all good I "

> babble (ng , 10)
[1] "you're the best for me We re good friends We're "

> babble (ng , 10)
[1] "think you're the best for me We re good friends "

> babble (ng , 10)
[1] "We're all good I think you're the best for me "

> babble (ng , 10)
[1] "like you I like you I think you're the best "

看上去,很符合预期。虽然比不是现在的大语言模型,能生成完整的语句,但是已经有了生成式模型的影子了。

本文的代码已上传到github:https://github.com/bsspirit/r-string-match/blob/main/ngram.r

转载请注明出处:
http://blog.fens.me/r-text-ngram/

This entry was posted in R语言实践

0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x