[TOC]
正式开始学习之前,先看看主要内容:
- 分别根据单词频度,单词位置 ,单词距离 ,来搜索相关网页并排序
- 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 urls
def 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分别代表了指向这个网页的权重和外链数
举个栗子:
[图片上传失败...(image-23c3aa-1513394933469)]
在上图中,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双曲正切函数
[图片上传失败...(image-111699-1513394933470)]
Sigmoid
[图片上传失败...(image-ee5c7c-1513394933470)]
- 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(['机器'], ['机器', '学习', '机器学习']))
最后,我们只需要把求结果的函数导入到排名中并分配权重就可以了,这里不做赘述
完整源码
有任何问题请私信或留言