机器学习之集体智慧编程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分别代表了指向这个网页的权重和外链数

举个栗子:

PageRank

​ 在上图中,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双曲正切函数

    tanh

  • Sigmoid

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(['机器'], ['机器', '学习', '机器学习']))

最后,我们只需要把求结果的函数导入到排名中并分配权重就可以了,这里不做赘述

完整源码

有任何问题请私信或留言

阅读全文
0 0
原创粉丝点击