HX04_Lesson04_Action03_SyntaxTree

Action03:设计你自己的句子生成器

import random
# 定语从句语法
grammar = '''
战斗 => 施法  , 结果 。
施法 => 主语 动作 技能 
结果 => 主语 获得 效果
主语 => 张飞 | 关羽 | 赵云 | 典韦 | 许褚 | 刘备 | 黄忠 | 曹操 | 鲁班七号 | 貂蝉
动作 => 施放 | 使用 | 召唤 
技能 => 一骑当千 | 单刀赴会 | 青龙偃月 | 刀锋铁骑 | 黑暗潜能 | 画地为牢 | 守护机关 | 狂兽血性 | 龙鸣 | 惊雷之龙 | 破云之龙 | 天翔之龙
获得 => 损失 | 获得 
效果 => 数值 状态
数值 => 1 | 1000 |5000 | 100 
状态 => 法力 | 生命
'''
def get_gramdict(grammar, linespit='\n',keysplit='=>'):
    """构造语法字典"""
    result = {}
    for line in grammar.split(linespit):
        if line != '':
            expr, actions = line.split(keysplit)
            result[expr.strip()] = [a.split() for a in actions.split('|')]
    return result
gramdict = get_gramdict(grammar)
gramdict
{'战斗': [['施法', ',', '结果', '。']],
 '施法': [['主语', '动作', '技能']],
 '结果': [['主语', '获得', '效果']],
 '主语': [['张飞'],
  ['关羽'],
  ['赵云'],
  ['典韦'],
  ['许褚'],
  ['刘备'],
  ['黄忠'],
  ['曹操'],
  ['鲁班七号'],
  ['貂蝉']],
 '动作': [['施放'], ['使用'], ['召唤']],
 '技能': [['一骑当千'],
  ['单刀赴会'],
  ['青龙偃月'],
  ['刀锋铁骑'],
  ['黑暗潜能'],
  ['画地为牢'],
  ['守护机关'],
  ['狂兽血性'],
  ['龙鸣'],
  ['惊雷之龙'],
  ['破云之龙'],
  ['天翔之龙']],
 '获得': [['损失'], ['获得']],
 '效果': [['数值', '状态']],
 '数值': [['1'], ['1000'], ['5000'], ['100']],
 '状态': [['法力'], ['生命']]}
def mygenerate(gramdict,target,isEng=False):
    """递归生成句子"""
    if target not in gramdict: return target
    blank = ''
    if isEng:
        blank = ' '
    action = random.choice(gramdict[target])
    return blank.join(mygenerate(gramdict, a, a.isalpha()) for a in action)
mygenerate(gramdict,'战斗')
'刘备 施放 单刀赴会,关羽 损失 1000 法力。'

 

总结: 生成字典时,内层value需要是嵌套的列表,否则生成句子的时候,随机选择将只得到一个词,但递归的过程中,可能需要逐一遍历value中值,比如:遍历['施法', ',', '结果', '。'],从而得到施法的动作,以及施法后的结果。

def game(N=10):
    #roles = ['张飞 ', '关羽', '赵云', '典韦', '许褚', '刘备', '黄忠', '曹操', '鲁班七号 ', '貂蝉']
    print('--------->游戏开始<---------')
    for i in range(N):
        result = mygenerate(gramdict, '战斗')
        print(result)
        #temp = result.split()    
        print("-" * 50)
    print('--------->游戏结束<---------')
game(10)
--------->游戏开始<---------
曹操 施放 天翔之龙,关羽 损失 100 生命。
--------------------------------------------------
黄忠 使用 单刀赴会,貂蝉 损失 100 生命。
--------------------------------------------------
黄忠 施放 狂兽血性,赵云 损失 100 生命。
--------------------------------------------------
黄忠 召唤 黑暗潜能,许褚 损失 5000 生命。
--------------------------------------------------
张飞 使用 破云之龙,鲁班七号 损失 1000 法力。
--------------------------------------------------
许褚 召唤 惊雷之龙,鲁班七号 损失 5000 生命。
--------------------------------------------------
曹操 召唤 破云之龙,关羽 损失 5000 法力。
--------------------------------------------------
貂蝉 使用 惊雷之龙,许褚 损失 5000 生命。
--------------------------------------------------
张飞 召唤 一骑当千,刘备 损失 100 法力。
--------------------------------------------------
典韦 使用 破云之龙,张飞 损失 5000 生命。
--------------------------------------------------
--------->游戏结束<---------

本节思考:
Action2: Paper Reading:Slope one predictors for online rating-based collaborative filtering. Daniel Lemire and Anna Maclachlan, 2007.
阅读收获:
英文阅读水平不行,读的一知半解。目前能get到的内容有:

论文中介绍了三种Slope One的算法
The SLOPE ONE Scheme: SlopeOne 算法
The WEIGHTED SLOPE ONE Scheme :加权 SlopeOne 算法
The BI-P
OLAR SLOPE ONE Scheme
通过与四种不同算法的对比,证明了Slope One算法的5大优点:
易于实现和维护:所有聚合的数据都应易于由平均工程师解释,算法应易于实现和测试;
可动态更新:添加新的评级应立即改变所有预测;
查询效率高:查询应该快速,可能以存储为代价;
对首次访问者的期望不高:评分较低的用户应收到有效的推荐。
在合理范围内准确:使用较小的牺牲得到相对不错的结果。
做对比的四种算法:
每个用户的平均值PER USER AVERAGE;
来自平均值的偏差BIAS FROM MEAN;
代表基于模型算法的基于调整余弦项的 ADJUSTED COSINE ITEM- BASED;
皮尔逊算法PEARSON,它代表基于内存的算法
以下为译文:

前言

基于评分的协同过滤是一种预测用户如何从其他用户评分中对给定产品进行评分的过程。 我们提出了三种相关Slope One算法,其预测因子以$f(x) = x + b$的形式,预先计算用户对某一产品和另一产品评分的平均差值。 Slope one算法易于实现,查询效率高,合理准确,支持在线推荐和动态更新,这使它们成为现实系统的良好候选。 本文提出了一种新的协同过滤参考方案——The basic SLOPE ONE 算法。 通过将用户喜欢的产品与用户不喜欢的产品分开考虑,我们获得了与基于内存的较慢方案对比的结果,超过了标准基准每个Movie和Movielens数据集,同时更好地满足了CF应用程序的需求。 关键词:协同过滤、推荐器、电子商务、数据挖掘、知识发现

介绍

基于在线评级的协作过滤CF查询由来自单个用户的(item、rating)对数组构成。 对该查询的响应是对用户尚未评级的item的(item、rating)对的预测。我们的目标是提供稳健的CF方案,即:

易于实现和维护:所有聚合的数据都应易于由平均工程师解释,算法应易于实现和测试;

可动态更新:添加新的评级应立即改变所有预测;

查询效率高:查询应该快速,可能以存储为代价;

对首次访问者的期望不高:评分较低的用户应收到有效的推荐。

在合理范围内准确:这些方案应与最准确的方案对比,但在准确性或可扩展性方面,取得较小的收益并不总是值得付出重大的牺牲。

本文的目的不是要比较各种CF算法的准确性,而是要证明Slope One方案可同时满足所有五个目标。尽管我们的方案简单,可更新,计算效率高且可扩展,但其准确性与放弃其他优势的方案相当。

我们的Slope One算法以直观的原理为用户提供商品之间的“人气差异”。 以成对的方式,我们确定一个item比另一个item好多少。衡量此差异的一种方法就是简单地减去两项的平均评分。 反过来,这种差异可以用来预测其他用户对这些项目中的一个的评价,并给出他们对另一个项目的评价。 考虑两个用户A和B,两个item I和J以及图1。用户A给项目I的评分为1,而用户B给项目I的评分为2,而用户A给项目J的评分为1.5。我们观察到项目J的评级比项目I高$1.5 - 1 = 0.5$分,因此我们可以预测用户B将给项目J评级为$2 + 0.5 = 2.5$。我们称用户B为被预测者用户,项目J为被预测者项目。对于每个未知等级,训练集中都存在许多这样的差异,我们取这些差异的平均值。此处介绍的slope one算法源于我们选择相关微分以得出单个预测的三种方式。 本文的主要贡献是提出了slope one CF预测器,并证明了它们与基于内存的方法具有竞争力,具有几乎相同的准确性,同时更适合于CF任务。

2相关工作 2.1基于内存和基于模型的模型 基于内存的协作过滤使用对用户之间的相似性度量来构建预测,通常是通过加权平均。 所选择的相似性度量决定了预测的准确性, 基于内存的CF的一些潜在缺点包括: 可伸缩性和对数据稀疏性的敏感性。 一般来说,依赖于用户之间相似性的方案不能预先计算用于快速在线推荐。 另一个关键问题是,基于内存的方案必须计算用户之间的相似性度量,这通常要求一些最小用户数量(例如,至少100个用户)输入一些最低数量的评级(例如,至少20个评级),包括当前用户。 我们将把我们的方案与一个著名的基于内存的方案,皮尔逊方案进行对比。

有许多基于模型的CF方法。有些基于线性代数(SVD, PCA,或特征向量)[3,6,7,10,15,16];或者更直接地借鉴人工智能的技术,如贝叶斯方法、潜在类和神经网络[1,2,9];或聚类[4,5]。 与基于内存的方案相比,基于模型的CF算法在查询时间上通常更快,尽管它们可能有昂贵的学习或更新阶段。 当查询速度至关重要时,基于模型的方案优于基于内存的方案。

我们可以使用以下代数术语将我们的预测变量与文献中描述的某些类型的预测变量进行比较。 我们的预测变量的形式为$f(x)= x + b$,因此名称为“ slope one”,其中b为常数,x为代表额定值的变量。 对于任何一对items,我们都会尝试找到最佳函数f,该函数可以从另一个item的评分预测一个item的评分。 对于每对项目,此函数可能有所不同。 CF方案将加权由预测变量生成的许多预测。 在[14]中,作者考虑了成对items之间的相关性,然后得出了用户评分的加权平均值作为预测指标。在其算法的简单版本中,其预测变量的形式为$f(x)= x$。 在他们算法的基于回归的版本中,他们的预测变量的形式为$f(x)= ax + b$。 在[17]中,作者也采用了$f(x)= ax + b$形式的预测变量。这两篇论文的研究的自然扩展是考虑形式为$f(x)= ax^2 + bx + c$的预测变量。 相反,在本文中,我们使用形式为$f(x)= = x + b$的朴素预测变量。我们也使用朴素的加权。在[14]中观察到,即使是基于回归的$f(x)= ax + b$算法也无法带来比基于内存的算法更大的改进。

因此,一个重要的结果证明,形式为$f(x)= = x + b$的预测变量可以与基于内存的模型竞争。

3 CF算法 我们提出了三种新的CF算法,并将我们提出的算法与四种参考算法进行了对比: 每个用户的平均值PER USER AVERAGE, 来自平均值的偏差BIAS FROM MEAN, 代表基于模型算法的基于调整余弦项的 ADJUSTED COSINE ITEM- BASED,和皮尔逊算法PEARSON,它代表基于内存的算法。

3.1 声明: 我们在描述方案时使用了以下表示法。 来自给定用户的评级,称为evaluation,表示为一个不完整的数组u,其中$u_{i}$是该用户给项目i的评级。 由所有在u中被评级的item构成的一组item的子集是S(u)。 训练集中所有评价的集合是χ的。 集合S中元素的个数是$card(S)$。 评价u中评级的平均值表示$\hat {u}$。 集合$S{i}(χ)$是所有评价u的集合χ使它们包含项目I(IS(U))。 给定两个评价u,v,我们将标量积hu,vi定义为iS(U)S(V)uivi。 预测,我们写P(U),表示一个向量,其中每个分量是对应于一个项目的预测:预测隐式依赖于χ的训练集。 3.2 Baseline基于统计的基准预测线打分 最基本的预测算法之一是由方程$P(u) = \hat_{u}$给出的每用户平均算法 the PER USER AVERAGE。 也就是说,我们预测用户将根据该用户的平均评分对所有内容进行评分。 另一种简单的方案称为偏离均值BIAS FROM MEAN(或有时称为:非个性化[8])。 计算公式为:$P(u)i = \hat{u} + \frat{1}{card(S_i(x))}\sum {vS_i(x)} v_i - \hat{v}$

也就是说,预测是基于用户的平均值加上训练集中所有用户对问题项与用户平均值的平均偏差。 我们也比较了基于项目的方法,它号称工作是最好的[14],它使用以下调整余弦相似度度量,给定两个项目i和j

预测结果作为这些措施的加权和得到: 3.3 PEARSON参考方案 由于我们希望证明我们的方案在预测能力上可以与基于内存的方案相媲美,因此,我们选择实施一种这样的方案作为该类的代表,并承认有许多此类文献记载的方案。 在最流行和最精确的基于内存的方案中,有PEARSON方案[13]。它采用χ中所有用户的加权总和的形式:

其中,γ是根据皮尔森相关性计算出的相似度:

与ρ=2.5,其中ρ是案件放大权。 案例放大降低了数据中的噪声:如果相关性很高,比如Corr=0.9,那么在案例放大后它仍然很高($0.9{2.5}=0.8$),而如果它很低,比如Corr=0.1,那么它就可以忽略不计($0.1=0.003$)。 皮尔森的相关性和案例放大被证明是一个合理准确的基于内存的CF方案,[2],尽管更准确的方案存在。

3.4 The SLOPE ONE Scheme The SLOPE ONE 算法考虑了来自其他用户的信息,这些用户对同一个item进行了评级(如:ADJUSTED COSINE ITEM-based),以及来自同一用户评级的其他项目(如:PERUSERAVERAGE)。 然而,这些方案还依赖于既不属于用户数组也不属于项目数组的数据点(例如:用户A在图中对项目I的评级),但仍然是评级预测的重要信息。 该方法的大部分优点来自未考虑在内的数据。 具体地说,只有那些与预测对象用户一起对某个共同项目进行了评级的用户的评级,以及只有预测对象用户也已经对项目进行评级的那些用户的评级,才进入The SLOPE ONE 算法下的评级预测。 形式上,给定两个评估数组$v_i$和$w_i$,且i = 1,...,n,我们搜索形式为$f(x)= x + b$的最佳预测变量,以通过使$\sum_{i}(v_i + b - w_i)^2$。相对于b求导并将导数设置为零,我们得到$b =\fac{\sum_{i}(w_i - v_i)^}{n}$。换句话说,常数b必须选择为两个数组之间的平均差。该结果激励了以下模型。 给定一个训练集χ,并且在某个用户评估u中分别给定评分uj和ui的任意两个项目j和i(标注为u∈Sj,i(χ)),我们考虑项目i相对于项目j的平均偏差如:

注意,不同时包含uj和ui的任何用户评估u均不包括在求和中。 $dev_{j,i}$定义的对称矩阵可以计算一次,并在输入新数据时快速更新。 假设$dev_{j,i} + u_i$ 是给定ui的uj的预测,则合理的预测因子可能是所有此类预测的平均值。

其中Rj = {i | i∈S(u),i = j,card(Sj,i(χ))> 0}是所有相关项的集合。有一个近似值可以简化此预测的计算。对于几乎所有项目对都具有评级的足够密集的数据集,即对于几乎所有i,j的card(Sj,i(χ))> 0,对于j∈,大多数时间Rj = S(u) / S(u)且当j∈S(u)时Rj = S(u)− {j}。由于¯u= ∑i∈S(u)ui card(S(u))'∑i∈Rj ui card(Rj) 对于大多数j,我们可以将SLOPE ONE方案的预测公式简化为: $P^{S1}(u_){j} = \hat{u} + \frac{1}{card(R_j)}\sum dev_{j,i}$

有趣的是,我们对SLOPE ONE的实施不取决于用户对单个商品的评分方式,而仅取决于用户的平均评分,并且关键在于用户对哪些商品评分。

3.5加权SLOPE ONE算法 SLOPE ONE的缺点之一是没有考虑观察到的等级数。直观地,要在给定用户A对项目J和K的评级的情况下预测用户A对项目L的评级,如果2000个用户对项目J和L进行评级,而只有20个用户对项目K和L对进行评级,则用户A对项目对的评级与用户A对项目K的评级相比,J可能是对项目L更好的预测指标。因此,我们将加权SLOPE ONE算法预测定义为以下加权平均值:

3.6双极斜率一方案 虽然权重有利于频繁出现的评级模式而不是不频繁出现的评级模式,但我们现在将考虑支持另一种特别相关的评级模式。 我们通过将预测分成两部分来实现这一点。 利用加权斜率- 1算法,我们分别从用户喜欢的项目和用户不喜欢的项目中得出一个预测。

给定一个评级等级,例如从 0 到 10,使用等级的中间 5 似乎是合理的,因为阈值和评级高于 5 的项目是喜欢的,而评级低于 5 的项目则不为。如果用户的评级均匀分布,这会很好地工作。但是,每个电影数据中超过 70% 的评分都高于比例的中间。 由于我们希望支持所有类型的用户,包括均衡、乐观、悲观和双模用户,因此我们将用户的平均值作为用户喜欢和不喜欢的项目之间的阈值。例如,乐观的用户,谁喜欢他们评价的每一个项目,被假定不喜欢的项目评级低于他们的平均评级。此阈值可确保我们的算法具有适合每个用户的合理数量的喜欢和不喜欢的项目。

他的论文表明,一个容易实现的基于平均评级差异的CF模型可以与更昂贵的基于内存的方案竞争。与目前使用的方案相比,我们的方法能够满足5个相对的目标。Slope One方案易于实现,可动态更新,查询效率高,对第一次访问的用户期望少,同时具有相当的准确性(例如:1.90 vs. 1.88 MAE的电影),以其他常见的报告方案。考虑到基于内存的方案在比较中相对复杂,这是值得注意的。我们的方法的一个进一步的创新是,将评级分成喜欢和不喜欢的子集可以是一种提高准确性的有效技术。希望在此提出的通用slopeone预测器将证明对CFcommunity有用,作为参考方案。

posted @ 2020-09-17 20:14  python坚持者  阅读(188)  评论(0编辑  收藏  举报