• 郑捷《机器学习算法原理与编程实践》学习笔记(第六章 神经网络初步)6.5 Boltzmann机算法


    6.5 Boltzmann机算法

    6.5.1 问题的提出

    6.5.2 模拟退化原理

    6.5.3 Boltzmann分布与退火过程

    6.5.4Boltzmann机类与退火过程

       Boltzmann网络初始时,需要根据参数设置一系列的初始值,主要参数在_init_中

      (1)构造方法如下

    class BoltzmannNet(object):
        def __init__(self):
            self.dataMat   = []        #外部导入的数据集
            self.MAX_ITER  = 2000      #外循环迭代次数
            Self.T0        = 1 000     #最高温度:这个温度变化范围应位于最大迭代范围
            self.Lambda    = 0.97      #温度下降参数
            self.iteration = 0         #达到最优时的迭代次数
            self.dist      = []        #存储生成的距离
            self.pathindx  = []        #存储生成的路径索引
            self.bestdist  = 0         #生成的最优路径长度
            self.bestpath  = []        #生成的最优路径

      (2)加载数据文件类

     def loadDataSet(self,filename):     #加载数据集
            self.dataMat     = []
            self.classLabels = []
            fr               = open(filename)
            for line in fr.readlines():
                lineArr = line.strip().split()
                self.dataMat.append([float(lineArr[0]),float(lineArr[1]),1.0])
                self.classLabels.append(int(float(lineArr[2])))
            self.dataMat = mat(self.dataMat)
            m,n          = shape(self.dataMat)
            self.nSampNum = m   #样本数量
            self.nSampDim = n-1 #样本维度

       (3)计算矩阵各向量之间的距离--欧式距离

     def distEclud(self,vecA,vecB):
            #欧式距离
            eps = 1.0e-6
            return linalg.norm(vecA-vecB) + eps

      (4)玻耳兹曼函数

     def boltzmann(self,new1,old1,T):
            return exp(-(new1-old1)/T)

      (5)计算路径长度

     def pathLen(self,dist,path):
            N = len(path)
            plen = 0
            for i in xrange(0,N-1):   #长度为N的向量,包含1~N的整数
                plen += dist[path[i],path[i+1]]
            plen += dist[path[0],path[N-1]]
            return  plen

      (6)交换新旧路径

     def changePath(self,old_path):
            N = len(old_path)
            if random.rand() < 0.25:   #产生两个位置,并交换
                chpos = floor(random.rand(1,2)*N).tolist()[0]
                new_path = copy.deepcopy(old_path)
                new_path[int(chpos[0])] = old_path[int(chpos[1])]
                new_path[int(chpos[1])] = old_path[int(chpos[0])]
            else:
                d = ceil(random.rand(1,3)*N).tolist()[0]
                d.sort()  #随机路径排序
                a = int(d[0])
                b = int(d[1])
                c = int(d[2])
            if a != b and b != c:
                new_path = copy.deepcopy(old_path)
                new_path[a,c-1] = old_path[b-1:c-1]+old_path[a:b-1]
            else:
                new_path = self.changePath(old_path)
            return new_path

       (7)绘制路径

    def drawPath(self,Seq,dataMat,color = 'b'):
            m,n = shape(dataMat)
            px  = (dataMat[Seq,0]).tolist()
            py  = (dataMat[Seq,1]).tolist()
            px.append(px[0])
            py.append(py[0])
            plt.plot(px,py,color)

       (8)绘制散点图

    def drawScatter(self,plt):
            px = (self.dataMat[:,0]).tolist()
            py = (self.dataMat[:,1]).tolist()
            plt.scatter(px,py,c = 'green',marker = 'o',s = 60)
            i = 65
            for x,y in zip(px,py):
                plt.annotate(str(chr(i)),xy = (x[0]+40,y[0]),color = 'black')
                i += 1

      (9)绘制趋势线

      def Trendline(self,plt,color = 'b'):
            plt.plot(range(len(self.dist)),self.dist,color)

    6.5.5 最短路径的实现

      Boltzmann网络的具体运行步骤如下

      第一步:导入数据,并根据配置参数初始化网络

      初始化网络函数如下:

      

        def initBMNet(self,m,n,distMat):
            self.pathindx = range(m)
            random.shuffle(self.pathindx)  #随机生成每个路径
            self.dist.append(self.pathLen(distMat,self.pathindx)) #每个路径对应的距离
            return self.T0,self.pathindx,m
    #第一步:导入数据,并根据配置参数初始化网络
        def train(self):  #主函数
            [m,n] = shape(self.dataMat)
            distMat = self.distEclud(self.dataMat,self.dataMat.T) #转换为邻接矩阵(距离矩阵)
            # T为当前温度,curpath为当前路径索引,MAX_M为内循环最大迭代次数
            [T,curpath,MAX_M] = self.initBMNet(m,n,distMat)
    
        #进入主循环,计算最优路径
            step = 0 #初始化外循环迭代
            while step <= self.MAX_ITER:   #外循环
                m = 0                       #内循环计数器
                while m <= MAX_M:          #内循环
                    curdist = self.pathLen(distMat,curpath) #计算当前路径距离
                    newpath = self.changePath(curpath)      #交换产生新路径
                    newdist = self.pathLen(distMat,newpath) #计算新路径距离
                    #判断网络是否是一个局部稳态
                    if (curdist > newdist):
                        curpath = newpath
                        self.pathindx.append(curpath)
                        self.dist.append(newdist)
                        self.iteration += 1       #增加迭代次数
                    else:                         #如果网络处于局部稳定状态,则执行玻尔兹曼函数
                        if random.rand()<self.boltzmann(newdist,curdist,T):
                            curpath = newpath
                            self.pathindx.append(curpath)
                            self.dist.append(newdist)
                            self.iteration += 1   #增加迭代次数
                m += 1
                step += 1
                T = T *self.Lambda   #降温,返回迭代,直至算法终止
        #第三步:提取最优路径
            self.bestdist = min(self.dist)
            indxes = argmin(self.dist)
            self.bestdist = self.pathindx[indxes]
        

     6.5.6 执行算法

      

    bmNet = BoltzmannNet()
    bmNet.loadDataSet("dataSet25.txt")
    bmNet.train()
    print u"循环迭代",bmNet.bestdist
    print  u"最佳路线",bmNet.bestpath
    #显示优化后的城市地图、路径图
    bmNet.drawScatter(plt)
    plt.show()
    
    bmNet.Trendline(plt) #绘制误差算法收敛曲线
    plt.show()

     全部代码:

    #coding:utf-8
    
    from numpy import *
    import copy
    import matplotlib.pyplot as plt
    
    class BoltzmannNet(object):
        def __init__(self):
            self.dataMat   = []        #外部导入的数据集
            self.MAX_ITER  = 2000      #外循环迭代次数
            self.T0        = 1000     #最高温度:这个温度变化范围应位于最大迭代范围
            self.Lambda    = 0.97       #温度下降参数
            self.iteration = 0         #达到最优时的迭代次数
            self.dist      = []        #存储生成的距离
            self.pathindx  = []        #存储生成的路径索引
            self.bestdist  = 0         #生成的最优路径长度
            self.bestpath  = []        #生成的最优路径
    
        def loadDataSet(self,filename):     #加载数据集
            self.dataMat     = []
            self.classLabels = []
            fr               = open(filename)
            for line in fr.readlines():
                lineArr = line.strip().split()
                # self.dataMat.append([float(lineArr[0]),float(lineArr[1]),1.0])
                self.dataMat.append([float(lineArr[0]),float(lineArr[1])])
                self.classLabels.append(int(float(lineArr[2])))
            self.dataMat = mat(self.dataMat)
            m,n          = shape(self.dataMat)
            self.nSampNum = m   #样本数量
            self.nSampDim = n-1 #样本维度
    
        def distEclud(self,vecA,vecB):
            #欧式距离
            distMat = zeros((vecA.shape[0],vecA.shape[0]))
            for i in range(len(vecA)):
                for j in range(len(vecA)):
                    distMat[i][j] = linalg.norm(vecA[i]-vecB[:,j])
            return  distMat
    
        def boltzmann(self,new1,old1,T):
            return exp(-(new1-old1)/T)
    
        def pathLen(self,dist,path):
            N = len(path)
            plen = 0
            for i in xrange(0,N-1):   #长度为N的向量,包含1~N的整数
                plen += dist[path[i],path[i+1]]
            plen += dist[path[0],path[N-1]]
            return  plen
    
        def changePath(self,old_path):
            N = len(old_path)
            if random.rand() < 0.25:   #产生两个位置,并交换
                chpos = floor(random.rand(1,2)*N).tolist()[0]
                new_path = copy.deepcopy(old_path)
                new_path[int(chpos[0])] = old_path[int(chpos[1])]
                new_path[int(chpos[1])] = old_path[int(chpos[0])]
            else:
                d = ceil(random.rand(1,3)*N).tolist()[0]
                d.sort()  #随机路径排序
                a = int(d[0])
                b = int(d[1])
                c = int(d[2])
                if a != b and b != c:
                    new_path = copy.deepcopy(old_path)
                    new_path[a:c-1] = old_path[b-1:c-1]+old_path[a:b-1]
                else:
                    new_path = self.changePath(old_path)
            return new_path
    
        def drawPath(self,Seq,dataMat,color = 'b'):
            m,n = shape(dataMat)
            px  = (dataMat[Seq,0]).tolist()
            py  = (dataMat[Seq,1]).tolist()
            px.append(px[0])
            py.append(py[0])
            plt.plot(px,py,color)
    
        def drawScatter(self,plt):
            px = (self.dataMat[:,0]).tolist()
            py = (self.dataMat[:,1]).tolist()
            plt.scatter(px,py,c = 'green',marker = 'o',s = 60)
            i = 65
            for x,y in zip(px,py):
                plt.annotate(str(chr(i)),xy = (x[0]+40,y[0]),color = 'black')
                i += 1
    
        def Trendline(self,plt,color = 'b'):
            plt.plot(range(len(self.dist)),self.dist,color)
    
        def initBMNet(self,m,n,distMat):
            self.pathindx = range(m)
            random.shuffle(self.pathindx)  #随机生成每个路径
            self.dist.append(self.pathLen(distMat,self.pathindx)) #每个路径对应的距离
            return self.T0,self.pathindx,m
    
        #第一步:导入数据,并根据配置参数初始化网络
        def train(self):  #主函数
            [m,n] = shape(self.dataMat)
            distMat = self.distEclud(self.dataMat,self.dataMat.T) #转换为邻接矩阵(距离矩阵)
            # T为当前温度,curpath为当前路径索引,MAX_M为内循环最大迭代次数
            [T,curpath,MAX_M] = self.initBMNet(m,n,distMat)
    
        #进入主循环,计算最优路径
            step = 0 #初始化外循环迭代
            while step <= self.MAX_ITER:   #外循环
                m = 0                       #内循环计数器
                while m <= MAX_M:          #内循环
                    curdist = self.pathLen(distMat,curpath) #计算当前路径距离
                    newpath = self.changePath(curpath)      #交换产生新路径
                    newdist = self.pathLen(distMat,newpath) #计算新路径距离
                    #判断网络是否是一个局部稳态
                    if (curdist > newdist):
                        curpath = newpath
                        self.pathindx.append(curpath)
                        self.dist.append(newdist)
                        self.iteration += 1       #增加迭代次数
                    else:                         #如果网络处于局部稳定状态,则执行玻尔兹曼函数
                        if random.rand()<self.boltzmann(newdist,curdist,T):
                            curpath = newpath
                            self.pathindx.append(curpath)
                            self.dist.append(newdist)
                            self.iteration += 1   #增加迭代次数
                    m += 1
                step += 1
                T = T *self.Lambda   #降温,返回迭代,直至算法终止
        #第三步:提取最优路径
            self.bestdist = min(self.dist)
            indxes = argmin(self.dist)
            self.bestpath = self.pathindx[indxes]
    
    bmNet = BoltzmannNet()
    bmNet.loadDataSet("dataSet25.txt")
    bmNet.train()
    print u"循环迭代",bmNet.iteration,u""
    print u"最优解",bmNet.bestdist
    print  u"最佳路线",bmNet.bestpath
    #显示优化后的城市地图、路径图
    bmNet.drawScatter(plt)
    plt.show()
    
    bmNet.Trendline(plt) #绘制误差算法收敛曲线
    plt.show()

    资料来源:郑捷《机器学习算法原理与编程实践》 仅供学习研究

  • 相关阅读:
    设计模式来替代if-else
    Cloneable接口的作用与深度克隆与浅度克隆
    IP地址分类
    MIME-TYPE
    Linux curl
    Cookie 跨域???
    冒烟测试
    @Valid、@Validated 、正则验证工具
    Node.js—第一个动态页面
    Node.js—小试牛刀-创建目录
  • 原文地址:https://www.cnblogs.com/wuchuanying/p/6394632.html
Copyright © 2020-2023  润新知