记录一下最近写的人工智能作业
随机游走实现:
随机游走模型假设一个冲浪者随机选择一个网页开始,然后随机选择链接进行浏览。例如,如果冲浪者在第二页,他们将在第一页和第三页之间随机选择作为访问的下一页(同一页面上的重复链接被视为单个链接,页面到自身的链接也被忽略)。如果他们选择了第三页,那么冲浪者将在第二页和第四页之间随机选择作为访问的下一页。
因此,一个页面的PageRank可以描述为随机冲浪者在任何时候在该页面的概率。毕竟,如果有更多的链接指向特定的页面,那么冲浪者最终会更有可能进入该页面。此外,来自更重要网站的链接比来自较少链接的不太重要的网站更有可能被点击,因此该模型还可以通过重要性对链接进行加权处理。
理解该模型的一种方式是将其视为马尔可夫链,其中每个页面表示一个状态,并且每个页面都有一个转移模型,在其中随机选择其链接。在每个时间步骤中,状态切换为当前状态链接到的页面之一。
通过从马尔可夫链中随机抽样状态,我们可以获得每个页面的 PageRank 的估计值。 我们可以从随机选择一个页面开始,然后随机跟踪链接,跟踪我们访问每个页面的次数。 在我们收集了所有样本之后(基于我们预先选择的数字),我们在每个页面上停留的时间比例可能是该页面排名的估计值。
def transition_model(corpus, page, damping_factor):
res = {}
for item in corpus.keys():
res[item] = (1 - damping_factor) / len(corpus)
if len(corpus[page]) > 0:
for item in corpus[page]:
res[item] += damping_factor / len(corpus[page])
return res
def sample_pagerank(corpus, damping_factor, n):
print(corpus)
res = {};
for item in corpus.keys():
res[item] = 0
page0 = random.choice(list(corpus.keys()))
for i in range(0, n):
# 找到该页面最可能链接到的下一个页面(根据transition_model得到的概率随机取一个最大的)
r = transition_model(corpus, page0, damping_factor);
sorted_values = sorted(r.values())
max_value = sorted_values[-1]
max_keys = [key for key, value in r.items() if value == max_value]
max_key = random.choice(max_keys)
page0 = max_key
res[max_key] += 1
for k in res:
res[k] = res[k] / SAMPLES
return res
迭代算法实现:
可以用递归的数学表达式来定义一个页面的PageRank。假设PR(p)是给定页面p的PageRank:随机冲浪者最终停留在该页面的概率。我们如何定义PR(p)?我们知道随机冲浪者可能以以下两种方式之一停留在该页面:
1、以1 - d的概率,冲浪者随机选择一个页面并停留在页面p。
2、以d的概率,冲浪者从页面i跟随链接到页面p。
第一个条件很容易用数学方式表达:它是1-d除以整个语料库中的页面总数N。这是因为1-d概率随机选择一个页面被平均分配在所有N个可能的页面中。
对于第二个条件,我们需要考虑每个可能链接到页面p的页面i。对于每个这样的入站页面i,让NumLinks(i)表示页面i上的链接数。每个链接到p的页面i都有自己的PageRank,即表示我们任何时候位于页面i上的概率PR(i)。由于从页面i到任何该页面的链接的概率相等,因此我们将PR(i)除以链接数NumLinks(i),以得到我们在页面i上并选择链接到页面p的概率。
def iterate_pagerank(corpus, damping_factor):
# 记录链接到该页面的所有页面
linkdc = {}
for item in corpus.keys():
linkdc[item] = []
# 这里可以想办法优化一下
for key in corpus:
for k in corpus:
if key in corpus[k]:
linkdc[key].append(k)
# 结果
res = {}
# 上一个结果,用于比较跳出循环
res_last = {}
for item in linkdc.keys():
res[item] = 1 / len(linkdc)
res_last = copy.deepcopy(res)
while 1:
for key in corpus:
t = 0
for it in linkdc[key]:
# PR(i)除以链接数NumLinks(i)的和
t += round(res_last[it] / len(corpus[it]), 4)
res[key] = round((1 - damping_factor) / len(corpus) + damping_factor * t, 4)
diff = 0
for key in res:
diff += abs(res[key] - res_last[key])
if diff < 0.001:
break
else:
res_last = copy.deepcopy(res)
return res
部分结果展示: