【学习笔记】1-两个小demo---sentence generate与 water pouring
1. 背景
跟踪学习某平台培训课程,写个笔记记录一下。刚听了第一节课,属于导论性质,通过两个小案例,大致描述了一下ai的思想和想要解决的问题,特此记录。工作之后,时间比较紧张,有段时间没有更新博客了,争取后续会坚持把学习的内容记录下来吧。
2. 案例
导论课大致讲了两个案例:1.基于语法规则匹配的句子生成;即:定义一些语法句式,目标是改变输入的情况下,不更改代码,得到输出(想阐述的是AI的一般思想,就是面对不同输入,通过模型,得到正确输出)。2.基于动态规划思想的倒水问题;即:两个不同容量的杯子,每次只操作一个杯子,如何得到目标水量。
2.1 句子生成
依据规则,随机生成句子。后续可拓展为,生成多个句子,依据概率判断生成的句子是否合理。
# coding=utf-8
import random
rules = """
复合句子 = 句子 , 连词 复合句子 | 句子
连词 = 而且 | 但是 | 不过
句子 = 主语 谓语 宾语
主语 = 你| 我 | 他
谓语 = 吃| 玩
宾语 = 桃子| 皮球
"""
def get_grammer_by_rules(rules):
# 按照规则拆分规则。分成句子成分,及各成分对应的词集合
rule_pattern = [rule.split('=') for rule in rules.split("\n") if rule.strip()]
# 构造规则对应的语法。构造成 句子成分:[, , ,] 的形式
grammer = {head.strip(): collects.split('|') for head, collects in rule_pattern}
return grammer
def get_sentence_by_grammer(grammer, target='句子'):
# 生成目标和语法不匹配
if target not in grammer:
return target
# 迭代符合句子里面的子句子,如果item为子句子,则再分割一次; 其他直接返回对应的值
sentence = ''.join([get_sentence_by_grammer(grammer, item) for item in random.choice(grammer[target]).split()])
return sentence
def main():
# 1. 依据描述(规则)生成对应的语法描述
rule_grammer = get_grammer_by_rules(rules)
# 2. 根据规则生成句子
sentence = get_sentence_by_grammer(rule_grammer, target='复合句子')
# TODO: 生成若干个句子,根据概率,判断句子的合理性;对应排除不合理的句子。
print(sentence)
if __name__ == '__main__':
main()
2.2 water pouring
# coding=utf-8
"""
需求:有两个容量不同的杯子,根据杯子容量的差别,每次操作一个杯子;
构造不同目标量
思路:1.根据杯子当前状态,列出所有可能的操作,以此确定杯子的下一状态
x, y : 杯子当前水量
X, Y : 杯子容量
操作:
(x, 0): y杯子水倒空(水量为0)
(0, y): x杯子水倒空
(x, Y): y杯子装满(水量为Y)
(X, y): X杯子装满(水量为X)
(x+y-Y, Y) if x+y > Y else (0, x+y): 将x重的水倒入y中
(X, x+y-X) if x+y > X else (x+y, 0): 将y重的水倒入x中
2.如果目标量,正好是 1 中的某种状态,返回对应的操作;
否则,迭代,继续探索某次操作后的水量的对应状态
"""
def get_stats(x, y, X, Y):
return {
(x, 0): '倒空y',
(0, y): '倒空x',
(x, Y): '灌满Y',
(X, y): '灌满X',
((x+y-Y, Y) if x+y >= Y else (0, x+y)): 'X->Y',
((X, x+y-X) if x+y >= X else (x+y, 0)): 'Y->X',
}
def solution(c1, c2, goal, start=(0, 0)):
"""
:param c1: 杯子1的容量
:param c2: 杯子2的容量
:param goal: 构造目标
:param start: 两个杯子初始的水量
:return: list 方案
"""
if goal in start:
return [start]
explored = set()
froniter = [ [('init', start)] ]
while froniter:
path = froniter.pop(0)
# 当前杯子中的水量
x, y = path[-1][-1]
for state, action in get_stats(x, y, c1, c2).items():
if state not in explored:
explored.add(state)
path_ = path + [(action, state)]
if goal in state:
return path_
else:
froniter.append(path_)
return []
def main():
# 1. 定义杯子的可能状态(操作),并返回
# get_stats()
# 2. 解决方案
res = solution(9, 4, 6, start=(0, 0))
print(res)
if __name__ == '__main__':
main()
3. 总结
- 两个案例很小,有点过时了,但是思想还是不错的。句子生成的例子中,阐述一般AI的思想就是面对变化的输入,代码(模型)不变,期望得到较好的输出;water pouring 的例子中,阐述了一点点动态规划的思想,利用当前阶段的可能状态,指导下一状态的生成。
- 代码中很巧妙的运用了迭代的实现,值得思考。