机器学习之集体智慧编程3:搜索与排名
来源:互联网 发布:怎么用c语言输入n个数 编辑:程序博客网 时间:2024/06/05 05:11
- 源数据
- 搜索与排名
- 搜索
- 归一函数
- 单词频度
- 单词位置
- 单词距离
- PageRank计分法
- 神经网络模拟用户行为
- 激活函数
- 前馈法
正式开始学习之前,先看看主要内容:
- 分别根据单词频度,单词位置 ,单词距离 ,来搜索相关网页并排序
- pagerank网站计分
- 神经网络模拟用户行为
- 前馈算法
- 反向传播学习法
源数据
由于书中数据源已经无法下载到了,所以自己从wiki中爬了一些网页的数据,此处整理出来方便使用
如果对爬虫内容不感兴趣的话可以在文末下载到相应代码,也可以得到数据源
在本文的数据分析中,我们要根据用户搜索的关键字来查找相关度最高的网页,即类似搜索引擎的功能,所以我们需要的数据有:网站网址,网站内容(以单词记录,记录位置),网站指向的链接
为了存储数据,需要建5张表:
- wordlocation单词位置表: id,wordid(单词的id),urlid(单词所在url对应id),position(单词在文中位置)
- wordlist单词表:id ,word,urlid(懒得连查所以这里也存了一份..)
- urllist网页表:id,url,rank(网页分数)
- linkwords关键字指向表:id,wordid,linkid单词指向的链接的id
- link网页指向表:id,fromid网站的id,toid网站指向的网站的id
有了这5张表之后,我们就可以愉快的开始爬虫之旅啦
在正式开始爬取网页数据之前,我们先把要爬的网页地址全部准备好:
# 爬取网址def getUrls(url_start='https://en.wikipedia.org/wiki/Tiger'): url_base = 'https://en.wikipedia.org' urls, allurls, newurls = set(), set(), set() urls.add(url_start) allurls.add(url_start) for i in range(1): for url_resource in urls: try: res = requests.get(url_resource, timeout=2) # 只看正文下的内容 links = BeautifulSoup(str(BeautifulSoup(res.content, 'lxml')('div', id='bodyContent')), 'lxml')('a') for link in links: if 'href' in dict(link.attrs): link_to = link['href'] # 外链和本文连接直接忽略 if link_to.startswith('http') or link_to.startswith('#'): continue url = parse.urljoin(url_base, link_to) if url.find("'") != -1: continue url = url.split('#')[0] newurls.add(url) except: pass urls = newurls.copy() allurls.update(newurls) with open('urls.txt', 'w') as f: for item in allurls: try: f.write(item + '\n') except: pass
运行上述代码可以生成一个包含了千余个网址的文件,我们就要从这些文件里取得我们要爬的分析数据,由于本文的主要记录搜索和排序的功能,具体的分析过程就不赘述了,直接贴代码:
def readUrls(): with open('urls.txt', 'r') as f: urls = f.read().split('\n') return urlsdef getUrlId(conn, cursor, url): # 查询当前url地址在表中的位置 cursor.execute('select id from urllist where url=%s', (url,)) urlid = cursor.fetchone() # 如果没有,新增并重新获取urlid if urlid is None: cursor.execute('insert into urllist(`url`) values(%s)', (url,)) conn.commit() cursor.execute('select id from urllist where url=%s', (url,)) urlid = cursor.fetchone() return urlid[0]# 根据url地址爬取相关数据,并写入数据库def parseData(urls): conn = connector.connect(user='root', password='wangweijie0', database='wwj') cursor = conn.cursor() worldid = 1 ignores = ['a', 'and', 'it', 'or', 'of', 'to', 'is', 'in', 'and', 'but', 'the', 'ma'] # 循环urlid for url in urls: try: res = requests.get(url, timeout=2) urlid = getUrlId(conn, cursor, url) soup = BeautifulSoup(str(BeautifulSoup(res.content, 'lxml')('div', id='bodyContent')), 'lxml') splitter = re.compile('\\W+') words = [t.lower() for t in splitter.split(soup.get_text()) if t != '' and t not in ignores] # 单词入库 for position in range(len(words)): # 写库 cursor.execute('insert into wordlist(`word`,`urlid`)values(%s,%s)', (words[position], urlid)) cursor.execute('insert into wordlocation(`urlid`,`wordid`,`position`)values(%s,%s,%s)', ( urlid, worldid, position + 1)) worldid += 1 conn.commit() # 只看正文下的内容 links = soup('a') for link in links: if 'href' in dict(link.attrs): link_to = link['href'] # 外链和本文连接直接忽略 if link_to.startswith('http') or link_to.startswith('#'): continue link_url = parse.urljoin('https://en.wikipedia.org', link_to) if link_url.find("'") != -1: continue link_url = link_url.split('#')[0] linkid = getUrlId(conn, cursor, link_url) cursor.execute('insert into link(`fromid`,`toid`)values(%s,%s)', (urlid, linkid)) # 查询当前href的字在word中而id不再linkwords中的第一个 cursor.execute( 'select ws.id from wordlist ws where ws.urlid=%s and ws.word=%s ', (urlid, link.text)) wordids = cursor.fetchall() if wordids is not None and len(wordids) > 0: for wordid in wordids: cursor.execute('select lw.wordid from linkwords lw where lw.wordid=%s ', (wordid[0],)) r = cursor.fetchone() if r is None or len(r) == 0: cursor.execute('insert into linkwords(`wordid`,`linkid`)values(%s,%s)', (wordid[0], linkid)) conn.commit() break conn.commit() except BaseException as e: conn.rollback() cursor.close() conn.close()
注意:由于wiki里侧边栏连接太多,所以我只爬取了正文的内容,侧边栏和下边栏,包括文章的标题都没有爬取
准备好数据之后就可以愉快的开始我们的搜索引擎之路了:
搜索与排名
根据关键字查表搜索可以得到和关键字相关的网页,但是乱序的网页中很难找到我们真正想要的,所以我们需要对网页进行一个排名,这样更容易找到用户想看到的东西,我们进行排名主要依靠单词频度,单词位置,单词距离 ,网页评分
下面就对这几个评估方法展开叙述:
搜索
首先,我们得构造一个方法,可以根据用户输入的关键字查找到相关的网页:
class search(): def __init__(self): self.conn = connector.connect(user='root', password='wangweijie0', database='wwj') self.cursor = self.conn.cursor() def __del__(self): if self.conn: self.conn.close # 查询的入口,kw是关键字字符串,以空格分割 def searchK(self, kw): kw.lower() words = kw.split(' ') self.result = {} for word in words: self.cursor.execute('select w.urlid,u.url from wordlist w,urllist u where w.word=%s and u.id=w.urlid', (word,)) # 查到所有连接的urlid urlids = self.cursor.fetchall() self.result[word] = urlids self.data = self.handledata() if len(self.data) == 0: print('无查询结果') else: self.getscoredlist()
在这里,我为了方便,直接取到了和关键字相关的网页和网页在数据库中的id,由于查到的网页有很多重复的,所以构造了一个handledata方法对查询结果进行了优化:
# 处理数据,返回共有的url和这些url出现的次数 def handledata(self): # 记录原始数据,但是把数据元素从[(1,),(2,)]变成了[1,2] data2 = self.result.copy() # 记录新数据,新数据之中去除了重复的url newdata = {} for word, urls in data2.items(): urlids = [u[0] for u in urls] # 把所有元素添加进来 urlset = [] for urlid in urlids: if urlid not in urlset: urlset.append(urlid) newdata[word] = urlset # 通过reduce函数,把新数据中的value变成set并求交集,之后在变回list,这样得到了两个的交集 urllist = list(reduce(lambda x, y: set(x) & set(y), [newdata[item] for item in newdata])) # 计算交集url出现的次数 return dict([(k, sum([data2[word].count(k) for word in data2])) for k in urllist])
调用函数,输入关键字就可以查到与之相关的网页了,虽然目前我们并没有做任何优化和排序,但是还是可以看出这些网页与关键字之间是有连续的
有必要先提前解释一下result和data的意思:result代表了初始的查询结果,数据很不好看,但是是原始数据,data是对result进行了优化,得到了关键字共同出现的url和这些关键字共同出现的次数之和
归一函数
由于我们再排序的时候用到了多种方法,有的方法是分数高的网页靠前,有的方法是分数低的网页靠前,所以我们需要一个归一化函数来把这些网页的评分进行优化,让他们的值域和变化方向一致
# 把数据都转化到0-1之间 def nomalizescores(self, scores, smallbetter=True): vsamll = 0.00001 # 小了好,小的分数高,小的当分子即可 if smallbetter: minscore = min(scores.values()) res = [(float(minscore) / max(vsamll, v), k) for k, v in scores.items()] # 大了好,大的分数高,大的当分母即可 else: maxscore = max(scores.values()) # 避免分母是0 if maxscore == 0: maxscore = vsamll res = [(float(v) / maxscore, k) for k, v in scores.items()] return dict(res)
这样我们就得到了一个值在0-1之间的评价,并且评价越高说明排名应该越靠前
单词频度
单词频度 就是用户搜索的单词在网页正文中出现的次数,我们有理由认为关键词出现次数多的网页更符合用户的预期,其排名应该更靠前
由于之前已经统计过网站出现的次数,所以此处很简单:
# 根据出现次数打分,多个单词的话以出现次数之和算def countscore(self): return self.nomalizescores(self.data, smallbetter=False)
单词位置
另一个判断网页相关度的简单方法是单词位置,如果单词出现的位置更靠前,比如出现在标题栏或者简介栏,那么这个网页应该跟我们搜索的关键词关联更紧密
# 根据单词之间的距离/单词位置计算 # 其实可以把单词位置记录在单词表,可以一起查出来结果,比这样效率高得多 # type记录计算距离还是计算位置 def disscore(self, type='distance'): # 按单词之间距离来 if type == 'distance': fn = lambda m, n: m - n # 按单词的位置来 else: fn = lambda m, n: m + n if len(self.result) == 1: return 1 positions = dict([(item, {}) for item in self.data]) totalscores = {} for urlid in self.data: for word in self.result: self.cursor.execute( 'select wl.position from wordlocation wl,wordlist w where w.word=%s and w.urlid=%s and wl.wordid=w.id', (word, urlid)) p = self.cursor.fetchall() positions[urlid][word] = [item[0] for item in p] # item是url,ps中包含了url中的关键字和出现的位置 for item, ps in positions.items(): totalscores.setdefault(item, 9999) # 每次取两个关键字比较 for k1 in ps: for k2 in ps: # 不比较一样的关键字 if k1 == k2: continue # 取两个关键字的所有值比较,取到差最小或者和最小的一对,记录 # 由于关键字可能不止两个,所以两两计算的结果加在一起作为最终的结果 totalscores[item] += min([min([abs(fn(m, n)) for m in ps[k1]]) for n in ps[k2]]) return self.nomalizescores(totalscores, smallbetter=True)
在上面的代码中,我们查到关键字的位置并构造了关于url和word的结果集,遍历结果集并把这些单词的位置求和,得到两两之间最小的位置和,这就是两个位置最靠前的单词的位置,重复这一过程,可以把多个关键字两两组合求得所有的关键字的位置总和
举个栗子方便理解:
查询关键字’a b c’,得到了一些url,我们取一个url,可以得到这个url里这些单词出现的位置
url:{a:[10,5,7,1],b:[13,7,2],c[18,4,9]}
那么我们可以先计算ab的最小位置和1+2=3,再计算ac的最小位置和1+4=5,bc的最小位置和2+4=6 ,所以最终计算结果应该是3+5+6=14
上述存在重复计算,但是由于归一化函数的存在,重复计算不会影响我们的最终判定结果,所以没有做处理
可能我描述的不太清楚,最主要还是理清思路,实在无法理解我说的是啥的可以debug跟一下代码,就明了
单词距离
我们查询多个单词的时候,更倾向于被查询的单词在文中出现的位置相近,如果两个单词出现在同一文章中但是距离过远,那可能就不是我们想要的结果
由于单词距离和单词位置都是根据每个关键字的位置来的,所以和单词位置合并到一起了,区别只是单词距离取得是位置差(也就是距离)的最小值,单词位置取得是位置和(也就是位置)的最小值
PageRank计分法
PageRank根据网页的权重以及网页指向其他链接的个数计算而成
这个值表示了用户在浏览时到达这个网页的可能性,值越大说明用户越倾向于进入这个网页,那这个网页权重显然应该更高
计算公式:
p=0.15+0.85*(p1/l1+p2/l2+…)
p和l分别代表了指向这个网页的权重和外链数
举个栗子:
在上图中,B网页有0.5的权重,指向4个网页,C网页有0.3的权重,指向四个网页,D网页有0.2的权重,只指向A
所以我们计算A的权重:
Ra=0.15+0.85*(0.5/4+0.3/4+0.2/1)=0.49
计算pagerank的方法其实很简单,只需要知道原网页权重和指向的个数就可以了,但是如果一组网页都没有权重,我们应该怎么办呢?
解决的办法是为每个网页都设置一个初始值,本文设置的是1,然后对多有网页进行pagerank的计算,替代初始值.多次执行计算之后就可以得到非常接近真实值的pagerank
# 计算网页分值 def pagerank(self): self.cursor.execute('select id from urllist') urlidlist = [item[0] for item in self.cursor.fetchall()] self.cursor.execute('select toid,fromid from link') linklist = self.cursor.fetchall() # todata里放着所有指向这个链接的urlid todata = {} # fromdata放着所有此链接指向的链接的数量 fromdata = {} for item in linklist: todata.setdefault(item[0], []) todata[item[0]].append(item[1]) fromdata.setdefault(item[1], 0) fromdata[item[1]] += 1 # 初始化所有rank为1 ranks = dict([(urlid, 1) for urlid in urlidlist]) # 循环30次计算pagerank,基本可以保证接近现实 for i in range(30): for urlid, fl in todata.items(): ranks[urlid] = 0.15 + 0.85 * sum([float(ranks[fromid]) / fromdata[fromid] for fromid in fl]) for urlid in ranks: self.cursor.execute('update urllist set rank=%s where id=%s', (ranks[urlid], urlid)) self.conn.commit()
神经网络,模拟用户行为
在线应用最大的优势就是可以得到用户操作的实时反馈
对于搜索引擎而言,可以获得用户在搜索时点击网页时的选择情况,让我们可以更好地展示用户喜欢的网页
在许多神经网络中,都以一组神经元相连,我们即将学习的这种称为多层感知机 ,他们都有一层输出层和一层输出层,以及中间的隐藏层.输入层和输出层用于交互,隐藏层用于筛选和计算
下面我们就开始进行模拟用户行为的神经网络训练
为了保存神经元之间的数据,首先我们得建数据库:
class searchnet(): def __init__(self): self.conn = connector.connect(user='root', password='wangweijie0', database='wwj') self.cursor = self.conn.cursor() def __del__(self): if self.conn: self.conn.close # 建表 def createtable(self): self.cursor.execute( 'create table inputhidden(`id` integer not null auto_increment,`fromid` varchar(80) not null,`toid` varchar(80) not null,`strength` float not null,primary key (`id`))auto_increment=1') self.cursor.execute( 'create table hiddenoutput(`id` integer not null auto_increment,`fromid` varchar(80) not null,`toid` varchar(80) not null,`strength` float not null,primary key (`id`))auto_increment=1') self.cursor.execute( 'create table hiddennode(`id`integer not null auto_increment, `createkey` varchar(80) not null,primary key (`id`))auto_increment=1') self.conn.commit()
这三张表分别记录了输入层到隐藏层的所有节点对应的id以及连接的强度(也可以称为权重),并记录了查询关键字
有了数据库之后我们需要两个方法用于设置和获取当前连接的强度:
# 获取链接强度,即链接权重 def getstrength(self, fromid, toid, layer): # 输入-隐藏,sd(strength-default)是默认strength if layer == 0: tablename, sd = 'inputhidden', -0.2 self.cursor.execute('select strength from inputhidden where fromid = %s and toid = %s', (fromid, toid)) res = self.cursor.fetchone() if res is None: return sd return res[0] # 隐藏-输出 elif layer == 1: tablename, sd = 'hiddenoutput', 0 self.cursor.execute('select strength from hiddenoutput where fromid = %s and toid = %s', (fromid, toid)) res = self.cursor.fetchone() if res is None: return sd return res[0] # 设置链接强度 def setstrength(self, fromid, toid, strength, layer): # 输入-隐藏 if layer == 0: tablename = 'inputhidden' self.cursor.execute('select strength from inputhidden where fromid=%s and toid=%s', (fromid, toid)) res = self.cursor.fetchone() # 无数据,插入数据 if res is None: self.cursor.execute('insert into inputhidden(`fromid`,`toid`,`strength`) values(%s,%s,%s)', (fromid, toid, strength)) # 有数据,更新 else: self.cursor.execute('update inputhidden set strength=%s where fromid=%s and toid=%s', (strength, fromid, toid)) # 隐藏-输出 elif layer == 1: tablename = 'hiddenoutput' self.cursor.execute('select strength from hiddenoutput where fromid=%s and toid=%s', (fromid, toid)) res = self.cursor.fetchone() # 无数据,插入数据 if res is None: self.cursor.execute('insert into hiddenoutput(`fromid`,`toid`,`strength`) values(%s,%s,%s)', (fromid, toid, strength)) # 有数据,更新 else: self.cursor.execute('update hiddenoutput set strength=%s where fromid=%s and toid=%s', (strength, fromid, toid)) self.conn.commit()
这里我尝试把tablename赋值给一个变量,然后把变量扔到sql语句中,但是一直报错,所以不得不采用这种重复代码的方法,如果您知道怎么动态设置tablename,望告知,万分感谢
在构建神经网络时,我们基本上都会先建立一个巨大的网络,把所有节点都构造出来.但是本例子中由于数据量不大,所以临时建立节点效率更高
每次用户传入一组数据,我们查看这组数据的节点是否已经建立,如果没有建立的话就添加节点
# 建立链接网 def generatehiddennode(self, words, urls): if len(words) > 3: return None # 通过排序保证key的唯一性 createkey = ' '.join(sorted([str(word) for word in words])) self.cursor.execute('select id from hiddennode where createkey=%s ', (createkey,)) res = self.cursor.fetchone() # 当前节点尚未建立,建立节点,设置权重(连接强度) if res is None: # 新建隐层节点 self.cursor.execute('insert into hiddennode(`createkey`) values(%s)', (createkey,)) for word in words: self.setstrength(word, createkey, 1 / len(words), 0) for url in urls: self.setstrength(createkey, url, 0.1, 1) self.conn.commit()
激活函数
如果每次我们都把输入值当做输出值这种线性做法来模拟网络,很多时候并不能满足我们的要求,所以需要引入非线性因素来让我们的网络功能更加丰富,也更加接近神经元(根据生物学的神经结构,刺激)
通常我们用得到的激活函数:
tanh双曲正切函数
Sigmoid
- ReLU
前馈法
通过输入正向计算输出的算法称为前馈算法,这个算法是开环的
在计算神经网络的输出值之前,我们需要把要分析的链接网矩阵构建起来
首先根据关键字找到相关的隐藏节点:
# 获取所有和输入层,输出层相关的隐藏节点 def getallhiddenids(self, words, urls): ll = {} createkey = ' '.join(sorted([str(word) for word in words])) for word in words: self.cursor.execute('select toid from inputhidden where fromid=%s', (word,)) for row in self.cursor.fetchall(): ll[row[0]] = 1 for url in urls: cur = self.cursor.execute('select fromid from hiddenoutput where toid=%s', (url,)) for row in self.cursor.fetchall(): ll[row[0]] = 1 return list(ll.keys())
构建链接矩阵:
# 建立链接矩阵 def setupnetword(self, words, urls): self.words = words self.urls = urls self.hiddens = self.getallhiddenids(words, urls) # 初始化输出数据,默认输入层输出都是1,wio,who,woo分别代表输入层,隐藏层,输出层的输出 self.wio = [1.0] * len(self.words) self.who = [0.0] * len(self.hiddens) self.woo = [0.0] * len(self.urls) # 初始化权重矩阵,ih,ho分别代表输入层到隐藏层和隐藏层到输出层 # 在矩阵中,隐藏层代表列名,输入输出都是行名 self.ih = [[self.getstrength(fromid, toid, 0) for toid in self.hiddens] for fromid in self.words] self.ho = [[self.getstrength(fromid, toid, 1) for fromid in self.hiddens] for toid in self.urls]
通过这个矩阵,我们把所有节点的相关信息(输入,输出,强度)全部拿到,就可以计算结果了
为了便于计算,我们假设输入层的输出全部为1,也就是隐藏层的输入是1
# 前馈算法,计算输出值 def feedfoward(self): for i in range(len(self.words)): # 输入层的输出结果默认为1 self.wio[i] = 1 # 对每一个隐藏层,计算到这个输隐藏层的输入,再通过tanh函数计算出输出 # j代表这是第几列,列名是隐藏层节点的名字 for j in range(len(self.hiddens)): sum = 0 # i代表第几行,行名输入层/输出层名字 # 这里对某个隐藏节点的所有输入与连接强度的乘积求和,得到隐藏节点的输入 for i in range(len(self.words)): sum += self.wio[i] * self.ih[i][j] # 利用激活函数求得输出 self.who[j] = tanh(sum) # 同上,计算输出层的输出 for i in range(len(self.urls)): sum = 0 for j in range(len(self.hiddens)): sum += self.who[j] * self.ho[i][j] # 利用激活函数求得输出 self.woo[i] = tanh(sum) return self.woo[:]
这里一定要理解,在输入-隐藏-输出这个模型中一共有3次激活(即内耗)两次传递.所以正常来说应该用到三次激活函数,两次损失函数,但是由于我们制定了输入层的输出是1,所以少用了一次激活函数
根据前馈算法中计算出的输出值,我们就知道误差有多少了,然后逆向传播,训练我们的神经网络,修改连接权重即可
# 反向传播,训练机器,改变链接权重 def backpropagate(self, targets, N=0.5): # 计算输出层的误差,这个误差也就是输出层的输入误差 ho_deviation = [0.0] * len(self.urls) for i in range(len(targets)): # 体现在最终输出的误差 error = targets[i] - self.woo[i] # 反函数求输出层的输入值并计算误差 ho_deviation[i] = self.dtanh(self.woo[i]) * error # 根据输出层误差计算隐藏层误差,这个误差是隐藏层的输入误差 ih_deviation = [0.0] * len(self.hiddens) for j in range(len(self.hiddens)): for i in range(len(self.urls)): error = 0 # 把误差按当前各个神经元的传递损耗分配下去,计算一个隐藏层的全部误差 # 通过这个损耗,已经把输出层的输入转化成了隐藏层的输出 error += ho_deviation[i] * self.ho[i][j] # 对当前隐藏层的输出求反,得到了隐藏层输入,进而求得隐藏层输入误差 ih_deviation[j] = self.dtanh(self.who[j]) * error # 修改隐藏层到输出层之间的连接强度 for j in range(len(self.hiddens)): for i in range(len(self.urls)): # 应该修改的值是隐藏层的输出值*误差 change = self.who[j] * ho_deviation[i] # N代表学习效率/成功率 self.ho[i][j] += N * change # 修改输入层到隐藏层之间的链接强度 for j in range(len(self.hiddens)): for i in range(len(self.words)): # 根据隐藏节点的误差求得输入层到隐藏层的误差 change = self.wio[i] * ih_deviation[j] self.ih[i][j] += N * change
这里我再解释一下,反向传播的时候,过了一次连接(隐藏层-输出层),两次激活(隐藏层和输出层),理解这点至关重要.
但是此处我还有一个地方比较疑惑,计算权重误差的时候居然是以上层输出*实际误差,而不是实际误差/上层输出,如果有大佬能解惑的话请告诉我0.0
计算完成之后我们需要把数据保存到数据库
def updateData(self): for j in range(len(self.hiddens)): for i in range(len(self.urls)): self.cursor.execute('update hiddenoutput set strength=%s where fromid=%s and toid=%s', (self.ho[i][j], self.hiddens[j], self.urls[i])) for j in range(len(self.hiddens)): for i in range(len(self.words)): self.cursor.execute('update inputhidden set strength=%s where fromid=%s and toid=%s', (self.ih[i][j], self.words[i], self.hiddens[j])) self.conn.commit()
训练的完整函数
def train(self, words, urls, target): # 生成节点 # 建立连接矩阵 # 获取链接强度 # 在反向训练之前调用前馈算法,这样可以计算好所有输出值 # 根据target生成输出层输出结果,反向传播修改矩阵数据 # 修改数据(输入层-隐藏层和隐藏层-输出层都要修改) self.generatehiddennode(words, urls) self.setupnetword(words, urls) self.feedfoward() targets = [0.0] * len(urls) targets[urls.index(target)] = 1 self.backpropagate(targets) self.updateData()
这样我们的训练函数就完成了,可以自己尝试一下哦,用法:
se = searchnet()for i in range(10): se.train(['机器', '学习'], ['机器', '学习', '机器学习'], '机器学习') print(se.getreslut(['机器', '学习'], ['机器', '学习', '机器学习']))print(se.getreslut(['机器'], ['机器', '学习', '机器学习']))
最后,我们只需要把求结果的函数导入到排名中并分配权重就可以了,这里不做赘述
完整源码
有任何问题请私信或留言
- 机器学习之集体智慧编程3:搜索与排名
- 集体智慧编程——搜索与排名-Python实现
- 机器学习入门 之 《集体智慧编程》 优化算法
- 机器学习入门 之《集体智慧编程》 决策树
- 机器学习入门 之 《集体智慧编程》 聚类(clustering)
- 机器学习入门 之《集体智慧编程》 推荐系统
- 机器学习入门 之 《集体智慧编程》 KNN算法
- 机器学习入门 之 《集体智慧编程》 寻找特征值
- 机器学习之集体智慧编程(1):推荐物品
- 《集体智慧编程》第4章 搜索与排名 个人笔记
- 集体智慧编程(三)搜索和排名
- 集体智慧编程第四章[搜索引擎与排名]总结
- 集体智慧编程第四章[搜索引擎与排名]总结
- python与集体智慧编程学习
- 集体智慧编程学习之推荐系统
- 集体智慧编程学习之优化系统
- 集体智慧编程学习之分类系统
- 集体智慧编程学习之决策树
- 将linux或安卓系统刷到开发板
- cent0S 7 安装 cdh5.13 笔记之五: 配置 hbase
- 方向导数与梯度
- 透彻的掌握 Spring 中@transactional 的使用
- 6. ZigZag Conversion
- 机器学习之集体智慧编程3:搜索与排名
- Android so库文件的区节section修复代码分析
- 使用svg-sprite-loader 遇到的问题
- HR4982是一种便于使用的内部集成了译码器的微特步进电机驱动器
- 我们真的需要前端框架吗??
- osi模型
- VIM插件: NERDTREE[树形目录]
- 牛客练习赛8
- Spark集群,多个版本Python/Python Package管理