简介

在对搜索结果进行排名时,如果需要返回用户的点击行为,就要用到神经网络去进行监督学习,此例中使用了多层感知机网络,以tanh()为激活函数,使用前馈算法计算输出,使用反向传播算法进行学习(调整权重矩阵),其中以用户的点击行为作为目标输出。

图片来源:https://www.zybuluo.com/hanbingtao/note/476663#an1

设置数据库

由于神经网络需要在用户查询时不断地训练,因此我们要将网络的信息存入数据库中
数据库中已有的表:涉及单词以及url
(1)数据库需要新增的表:
1.一张隐藏层的表:hiddennode(create_key)
2.一张连接输入层与隐藏层的表:wordhidden(fromid,toid,strength)
3.一张连接隐藏层和输出层的表:hiddenurl(fromid,toid,strength)

class searchnet:def __init__(self, dbname):self.con = sqlite3.connect(dbname)def __del__(self):self.con.close()def maketables(self):self.con.execute('drop table if exists hiddennode')self.con.execute('drop table if exists wordhidden')self.con.execute('drop table if exists hiddenurl')self.con.execute('create table hiddennode(create_key)')self.con.execute('create table wordhidden(fromid,toid,strength)')self.con.execute('create table hiddenurl(fromid,toid,strength)')self.con.commit()

(2)建立一个方法获取两个节点之间的连接强度,如果两个节点的连接之前未出现过(即出现了新连接),则返回连接强度的默认值

 #判断当前连接的强度 新连接只在必要时才会被创建,此方法在连接不存在时会返回一个默认值def getstrength(self,fromid,toid,layer):if layer==0:table='wordhidden'else:table='hiddenurl'res=self.con.execute('select strength from %s where fromid=%d and toid=%d' %(table,fromid,toid)).fetchone()if res==None:if layer==0:return -0.2if layer==1:return 0else:return res[0]

(3)建立一个setstrength()方法,判断连接是否存在,并用新的强度值更新连接或创建连接。

 #判断连接是否已存在,并利用新的强度值更新连接或创建连接def setstrength(self,fromid,toid,layer,strength):if layer==0:table='wordhidden'else:table='hiddenurl'#在层级表中查找索引号res=self.con.execute('select rowid from %s where fromid=%d and toid=%d' %(table,fromid,toid)).fetchone()if res==None:self.con.execute('insert into %s (fromid,toid,strength) values (%d,%d,%f)' %(table,fromid,toid,strength))else:rowid=res[0]self.con.execute('update %s set strength=%f where rowid=%d' %(table,strength,rowid))

(4)每传入一组从未见过的单词组合,该函数就会在隐藏层中建立一个新的节点。随后,函数会为单词与隐藏节点之间,以及隐藏节点与输出节点(url)之间,建立起具有默认权重的连接

 #每传入一组从未见过的单词组合,该函数就会在隐藏层中建立一个新的节点#[wordids]->wordhidden->hiddennode->hiddenurl->[urls]#hiddennode(create_key)#wordhidden(fromid,toid,strength)#hiddenurl(fromid,toid,strength)def generatehiddennode(self,wordids,urls):if len(wordids)>3:return None#检查我们是否已经为这组单词建好了一个节点 单词节点排序例 "1_2_3"#先排序,方便检查createkey='_'.join(sorted([str(wi) for wi in wordids]))res=self.con.execute("select rowid from hiddennode where create_key='%s'" %createkey).fetchone()#如果没有,则建立之if res==None:cur=self.con.execute("insert into hiddennode (create_key) values ('%s')" %createkey)hiddenid=cur.lastrowid#设置默认权重for wordid in wordids:self.setstrength(wordid,hiddenid,0,1.0/len(wordids))for urlid in urls:self.setstrength(hiddenid,urlid,1,0.1)self.con.commit()

前馈法

前馈法接受一组单词作为输入,激活网路中的连接,针对url给出一组输出
(1)建立一个方法,从数据库中查询出节点与连接的信息,然后在内存中建立起与某项查询相关的那一部分网络(每次使用前馈法计算输出时,并不会用到所有的隐藏层节点,只会用到与查询单词相关的隐藏层节点)
注意:
python3中不支持对dict的keys()进行索引

    #从隐藏层中找出与查询单词以及url相关的所有节点def getallhiddenids(self,wordids,urlids):l1={}for wordid in wordids:#找出所有查询的单词对应的隐藏层的节点cur=self.con.execute('select toid from wordhidden where fromid=%d' %wordid)for row in cur:l1[row[0]]=1for urlid in urlids:cur=self.con.execute('select fromid from hiddenurl where toid=%d' %urlid)for row in cur:l1[row[0]]=1#python3不支持dict的key索引return list(l1.keys())

(2)建立一个方法,为searchnet定义多个实例变量,包括:
1.单词列表、查询节点,URL
2.单词节点的输出、查询节点的输出、URL节点的输出
3.每个节点间的权重值

    #建立起神经网络来def setupnetwork(self,wordids,urlids):#值列表self.wordids=wordidsself.hiddenids=self.getallhiddenids(wordids,urlids)self.urlids=urlids#节点输出self.ai=[1.0]*len(self.wordids)self.ah=[1.0]*len(self.hiddenids)self.ao=[1.0]*len(self.urlids)#建立权重矩阵self.wi=[[self.getstrength(wordid,hiddenid,0) for hiddenid in self.hiddenids] for wordid in self.wordids]self.wo=[[self.getstrength(hiddenid,urlid,1) for urlid in self.urlids] for hiddenid in self.hiddenids]

(3)构造前馈算法,算法接受一列输入,将其推入网络,然后返回所有输出层节点的输出结果
选择输入(搜索词)->加权并激活->选择对应的查询节点(隐藏层)->加权并激活->url节点(输出,也是给定一个url的范围)

    #构造前馈算法 算法接受一列输入,将其推入网络,然后返回所有输出层节点的输出结果#本例中由于已经构造了一个只与查询条件中的单词相关的网络,因此所有来自输入层节点的输出结果总是1#不同的单词组合决定的是采用哪几个查询节点def feedforward(self):#查询单词是仅有的输入for i in range(len(self.wordids)):self.ai[i]=1#隐藏层节点的活跃程度for j in range(len(self.hiddenids)):sum=0.0for i in range(len(self.wordids)):sum+=self.ai[i]*self.wi[i][j]self.ah[j]=tanh(sum)#输出层节点的活跃程度for k in range(len(self.urlids)):sum=0.0for j in range(len(self.hiddenids)):sum=sum+self.ah[j]*self.wo[j][k]self.ao[k]=tanh(sum)return self.ao[:]

(4)生成结果,从建立网络到前馈

    def getresult(self,wordids,urlids):self.setupnetwork(wordids,urlids)return self.feedforward()

反向传播法训练

具体的步骤已经做了笔记,且可以参考如下网址,讲得很好:
https://www.zybuluo.com/hanbingtao/note/476663#an1
也是一系列固定的步骤

    #反向传播法def backPropagate(self,targets,N=0.5):#计算输出层的误差output_deltas=[0.0]*len(self.urlids)for k in range(len(self.urlids)):error=targets[k]-self.ao[k]output_deltas[k]=dtanh(self.ao[k])*error#计算隐藏层的误差hidden_deltas=[0.0]*len(self.hiddenids)for j in range(len(self.hiddenids)):error=0.0for k in range(len(self.urlids)):error=error+output_deltas[k]*self.wo[j][k]hidden_deltas[j]=dtanh(self.ah[j])*error#更新输出权重for j in range(len(self.hiddenids)):for k in range(len(self.urlids)):change=output_deltas[k]*self.ah[j]self.wo[j][k]=self.wo[j][k]+N*change#更新输入权重for i in range(len(self.wordids)):for j in range(len(self.hiddenids)):change=hidden_deltas[j]*self.ai[i]self.wi[i][j]=self.wi[i][j]+N*change

(2)然后将前面函数集合到一个函数,用于训练
注意:
每一次反向传播学习前,需要重新前馈一下,因为此时输出值已经发生了变化

    #更新数据库def updatedatabase(self):#将值存入数据库for i in range(len(self.wordids)):for j in range(len(self.hiddenids)):self.setstrength(self.wordids[i],self.hiddenids[j],0,self.wi[i][j])for j in range(len(self.hiddenids)):for k in range(len(self.urlids)):self.setstrength(self.hiddenids[j],self.urlids[k],1,self.wo[j][k])self.con.commit()#聚集各类方法 输入单词ID urlid 选择的urldef trainquery(self,wordids,urlids,selectedurl):#如有必要,生成一个隐藏节点self.generatehiddennode(wordids,urlids)self.setupnetwork(wordids,urlids)self.feedforward()targets=[0.0]*len(urlids)targets[urlids.index(selectedurl)]=1.0self.backPropagate(targets)self.updatedatabase()

与搜索引擎结合

(1)让排序的结果输出,主要还是为了返回单词ID和urlid(好像可以不需要。。。)

    #输出排序后的结果def query(self,q):rows,wordids=self.getmatchrows(q)scores=self.getscoredlist(rows,wordids)rankedscores=sorted([(score,url) for (url,score) in scores.items()],reverse=1)for (score,urlid) in rankedscores[0:10]:print('%f\t%d %s' %(score,urlid,self.geturlname(urlid)))#返回单词ID以及urlIDreturn wordids,[r[1] for r in rankedscores[0:10]]

(2)建立一个新的基于神经网络的评分算法

    #利用神经网络去进行排序def nnscore(self,rows,wordids):#获得一个由唯一的URL ID构成的有序列表urlids=[urlid for urlid in set([row[0] for row in rows])]nnres=mynet.getresult(wordids,urlids)scores=dict([(urlids[i],nnres[i]) for i in range(len(urlids))])return self.normalizescores(scores)

(3)更改weights,训练后排序输出

e=searcher('searchindex.db')
rows,wordids=e.getmatchrows("functional programming")
urlids=[]
for row in rows:urlids.append(row[0])
#给urlids去重 重复的节点过多会对神经网络有影响
t=set(urlids)
urlids=list(t)
for i in range(5):mynet.trainquery(wordids,urlids,220)#打印出来的应该是[(x1,x2,x3)...]的形式
#其中x1表示url的id,具体url可用过id在urllist中找到
#x2表示查询的第一个单词在该url对应的网页提取出来的文本的具体位置
#x3表示查询的第二个单词在该url对应的网页提取出来的文本的具体位置
#print(e.getmatchrows("functional programming"))
#输出查询到的排在前十的url
e.query("functional programming")
#e.calculatepagerank()

这神经网络搞了半天。。。

python算法应用(七)——搜索与排名3(点击跟踪网络的设计)相关推荐

  1. python算法专项(六)——Tensorflow原理基础,三层网络

    目录 1-随机数生成 2-三层网络拟合一个y = sinx 3-三层网络拟合多个函数(y = sinx,y =cosx,y = x**2) 训练注意事项 步长设置代码样例 样本设置.标签设置 中间层设 ...

  2. 【Python算法系列十一】二叉树的3种遍历方式

    二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次. 遍历二叉树的方法主要分 3 种:先序遍历.中序遍历和后序遍历: 先序遍历指最先遍历节点本身, ...

  3. Python数据结构学习笔记——搜索与排序算法

    目录 一.搜索 (一)搜索的方法 (二)顺序搜索 (三)二分搜索 二.排序 内排序和外排序 (一)冒泡排序 (二)选择排序 (三)插入排序 (四)希尔排序 (五)归并排序 (六)快速排序 总结 一.搜 ...

  4. python的算法是指_Python算法的七个重要特征

    算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出.如果一个算法有缺陷,或不适合 ...

  5. 今日头条的排名算法_今日头条搜索seo排名怎么做? 今日头条搜索排名规则...

    今日 既然今日头条宣布做搜索引擎,怎么少的了"头条seo"的研究呢? 一."头条seo"是什么? 头条seo指的是在今日头条app上用关键词搜索结果排名靠前.头 ...

  6. 今日头条的排名算法_今日头条搜索seo排名怎么做 今日头条搜索排名规则

    既然今日头条宣布做搜索引擎,怎么少的了"头条seo"的研究呢? 一."头条seo"是什么? 头条seo指的是在今日头条app上用关键词搜索结果排名靠前.头条号称 ...

  7. 数据结构与算法(python):广度优先搜索(Breadth First Search,BFS)和深度优先算法(Depth First Search,DFS)

    参考自 MOOC数据结构与算法Python版 目录 一.广度优先搜索 1.1 BFS算法过程 1.2 广度优先搜索算法分析 二.深度优先搜索 2.1 骑士周游 2.1.1 问题定义 2.1.2 构建骑 ...

  8. 常用算法2 - 广度优先搜索 深度优先搜索 (python实现)

    1. 图 定义:图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合. 简单点的说:图由节点和边组成.一 ...

  9. 如何利用亚马逊的底层逻辑是什么 寻找爆品搜索词排名?算法 it

    在亚马逊品牌分析刚出来的时候,小编就赶紧用上了,现在看来已经是熟能生巧了,今天小编就来说说如何使用亚马逊品牌分析. 来说说我是用的体验吧 品牌分析功能是目前最精准的关键词分析工具.毕竟是官方的后台数据 ...

最新文章

  1. 我的csdnmark
  2. 自动化发布-GitLab WEB Hooks 配置
  3. C++语言之Lambda函数与表达式
  4. python允许无止境的循环_ParisGabriel:Python无止境 day03
  5. VsCode搭建Java开发环境(Spring Boot项目创建、运行、调试)
  6. CSDN 代码不能语法高亮的原因
  7. Eclipse .class文件中文乱码
  8. iMazing与iTunes 两款iOS设备管理器区别 在备份操作上的对比
  9. java案例代码17--正则表达式小案例
  10. 手机投屏电视机的原理
  11. (附源码)ssm考试题库管理系统 毕业设计 069043
  12. ITMO-HDU Image Processing Lab4 Report
  13. 健身 宏效 -大道至简
  14. 尚学堂视频笔记五:IO流
  15. C++迷宫最短路径问题BFS
  16. SaaS 长河下,AfterShip 技术升级的“加减法”
  17. 大数据之统计股票开盘和收盘平均价
  18. 【华为路由器基本ACL过滤配置】
  19. Java枚举类与注解
  20. 工作之余如何有效学习提升

热门文章

  1. 在线考试 ajax,关于在线考试使用ajax一问?
  2. 中移4G模块-ML302-OpenCpu开发-PCF8591测量电压
  3. pdfplumber解析pdf文件
  4. java 重载 大于_详解java重载与覆写的区别
  5. 九毛九集团java_JAVA数组课后作业
  6. vb子程序未定义怎么改怎么办_vb中子程序或者函数未定义!求教解决方案,
  7. XAF-UI元素概述
  8. mysql基础,DISTINCT关键字
  9. 观察者模式在android网络监控下的运用
  10. ios 内联函数 inline ---分解LFLiveKit