郑捷《机器学习算法原理与编程实践》学习笔记(第六章 神经网络初步)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()

 

 

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

posted on 2017-02-14 17:32  金秀  阅读(367)  评论(0编辑  收藏  举报

导航