1,写入语法规则
simple_grammar = """
sentence => noun_phrase verb_phrase #句子语法结构:名词后面接上动词
noun_phrase => Article Adj* noun #名词词组:形容词+名词
Adj* => null | Adj Adj*
verb_phrase => verb noun_phrase
Article => 一个 | 这个
noun => 女人|篮球|桌子|小猫
verb => 看着|坐在|听着|看见
Adj =>蓝色的|好看的|小小的
"""
another_grammar = """
#
"""
2.随机选择几个形容词进行输出
import random
def adj(): return random.choice('蓝色的|好看的|小小的'.split('|')).split()[0]
def adj_star():
return random.choice([lambda:'',lambda:adj()+adj_star()])()
def adj_star():
return random.choice([lambda:'',lambda:adj()+adj_star()])()
adj_star()
但我们发现更换了语法,会发现所有程序都需要重新写
adj_grammar = """
Adj* => null | Adj Adj*
Adj => 蓝色的|好看的|小小的
"""
def create_grammar(grammar_str, split='=>',line_split='\n'):
grammar = {}
for line in grammar_str.split(line_split):
if not line.strip():continue
exp,stmt = line.split(split)
grammar[exp.strip()] = [s.split() for s in stmt.split('|')]
return grammar
grammar = create_grammar(adj_grammar)
grammar['Adj*']
choice = random.choice
def generate(gram, target):
if target not in gram: return target #means target is a terminal expression
expanded = [generate(gram,t) for t in choice(gram[target])]
return ''.join([e if e !='/n' else '\n' for e in expanded if e !='null'])
#递归调用函数、
generate(gram,sentence) target=sentence
expand=[]
=>1. if sentence not in gram
=>2. gram[sentence] = [['noun_phrase', 'verb_phrase']], for t in [nount_phrase,verb_phrase]
generate(gram,noun_phrase)
==>1. if noun_phrase not in gram
==>2. gram[noun_phrase] = [['Article', 'Adj*', 'noun']] for t in ['Article', 'Adj*', 'noun']
generate(gram, Article )
==> 1. if Article not in gram
==> 2. gram[Article] = [['一个'], ['这个']] t = ["这个"] t="这个"
generate(gram,"这个")
==>1 if "这个" not in gram ==> return "这个"
generate(gram,"Adj*")
==>1. if Adj* not in gram
==>2. gram["Adj*"] = [['null'],['Adj','Adj*']] t = ["noun"] t="noun"
expand = ['一个','好看的','小猫']#让语句学到正确的词汇排列顺序,按照词汇的排列顺序将语句输出,输出"一个好看的小猫"
example_grammar = create_grammar(simple_grammar)
generate(gram=example_grammar, target='sentence')#按语法规则随机输出语句
host = """
host = 寒暄 报数 询问 业务相关 结尾
报数 = 我是 数字 号 ,
数字 = 单个数字 | 数字 单个数字
单个数字 = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
寒暄 = 称谓 打招呼 | 打招呼
称谓 = 人称,
人称 = 先生 | 女士 |小朋友
打招呼 = 你好 | 您好
询问 = 请问你要 | 您需要
业务相关 = 玩玩 具体业务
玩玩 = null
具体业务 = 喝酒 | 打牌 | 打猎 | 赌博
结尾 = 吗?
"""
for i in range(20):
print(generate(gram=create_grammar(host, split='='),target='host'))#随机选择的词汇生成语法规则的语句
怎样生成语义合理的一句话,上下文对应的意思不相同,使用句子的出现次数算出概率值,求出P(sentence)频率与概率的区别,频率约等于概率。
Language Model:
The probability of a sentence.一个句子出现的可能性
N-gram Models
1-gram(Unigram) 2-gram(Bigram)
条件概率:
P(A) P(A|B)=A,B同时发生的概率除以B发生的概率
S是sentence句子,W1,W2,W3,...,Wn
是每一个句子中单词出现的概率相乘。
每一单词的概率是基于前面单词序列的基础之上的,将每个单词的序列概率相乘
一开始求十个词
独立性假设:我要去打篮球,P是篮球,我要去打篮球P(篮球|我,要,去,打)
距离越近的词汇概率越相近P(篮球|我,要,去,打)约等于P(篮球|打)
(马尔可夫性)P(篮球|我,要,去,打)约等于P(篮球|打)(2-gram)约等于P(篮球|去,打)(3-gram).....(n-gram)基于前面的n-1个词
n-gram就是将每一个式子相乘得出结果:P(Wn|Wn-1)P(Wn-1|Wn-2)P(Wn-2|Wn-3)...P(W2|W1)P(W1)
两个词在语料中的概率
平滑方法P(Wk|Wk-1) = Count(Wk,Wk-1)/Count(Wk) = Count(Wk,Wk-1)+1/Count(Wk)+|v|
Count(Wk)单个词的个数,|V|是指不同词的个数,所以将序列个数加一除以单个词的个数加上所有不同词的个数,加上V的原因在于不同词的个数是进行一个平滑化的,将分母变大以便数字的小于1