python实现SOM算法


Posted in Python onFebruary 23, 2018

算法简介

SOM网络是一种竞争学习型的无监督神经网络,将高维空间中相似的样本点映射到网络输出层中的邻近神经元。

训练过程简述:在接收到训练样本后,每个输出层神经元会计算该样本与自身携带的权向量之间的距离,距离最近的神经元成为竞争获胜者,称为最佳匹配单元。然后最佳匹配单元及其邻近的神经元的权向量将被调整,以使得这些权向量与当前输入样本的距离缩小。这个过程不断迭代,直至收敛。

  • 网络结构:输入层和输出层(或竞争层),如下图所示。
  • 输入层:假设一个输入样本为X=[x1,x2,x3,…,xn],是一个n维向量,则输入层神经元个数为n个。
  • 输出层(竞争层):通常输出层的神经元以矩阵方式排列在二维空间中,每个神经元都有一个权值向量。
  • 假设输出层有m个神经元,则有m个权值向量,Wi = [wi1,wi2,....,win], 1<=i<=m。

python实现SOM算法

算法流程:

1. 初始化:权值使用较小的随机值进行初始化,并对输入向量和权值做归一化处理
          X' = X/||X||
          ω'i= ωi/||ωi||, 1<=i<=m
          ||X||和||ωi||分别为输入的样本向量和权值向量的欧几里得范数。

2.将样本输入网络:样本与权值向量做点积,点积值最大的输出神经元赢得竞争,
(或者计算样本与权值向量的欧几里得距离,距离最小的神经元赢得竞争)记为获胜神经元。

3.更新权值:对获胜的神经元拓扑邻域内的神经元进行更新,并对学习后的权值重新归一化。
        ω(t+1)= ω(t)+ η(t,n) * (x-ω(t))
        η(t,n):η为学习率是关于训练时间t和与获胜神经元的拓扑距离n的函数。
        η(t,n)=η(t)e^(-n)
        η(t)的几种函数图像如下图所示。

4.更新学习速率η及拓扑邻域N,N随时间增大距离变小,如下图所示。

5.判断是否收敛。如果学习率η<=ηmin或达到预设的迭代次数,结束算法。

python实现SOM算法python实现SOM算法

python代码实现SOM

import numpy as np
import pylab as pl

class SOM(object):
  def __init__(self, X, output, iteration, batch_size):
    """
    :param X: 形状是N*D, 输入样本有N个,每个D维
    :param output: (n,m)一个元组,为输出层的形状是一个n*m的二维矩阵
    :param iteration:迭代次数
    :param batch_size:每次迭代时的样本数量
    初始化一个权值矩阵,形状为D*(n*m),即有n*m权值向量,每个D维
    """
    self.X = X
    self.output = output
    self.iteration = iteration
    self.batch_size = batch_size
    self.W = np.random.rand(X.shape[1], output[0] * output[1])
    print (self.W.shape)

  def GetN(self, t):
    """
    :param t:时间t, 这里用迭代次数来表示时间
    :return: 返回一个整数,表示拓扑距离,时间越大,拓扑邻域越小
    """
    a = min(self.output)
    return int(a-float(a)*t/self.iteration)

  def Geteta(self, t, n):
    """
    :param t: 时间t, 这里用迭代次数来表示时间
    :param n: 拓扑距离
    :return: 返回学习率,
    """
    return np.power(np.e, -n)/(t+2)

  def updata_W(self, X, t, winner):
    N = self.GetN(t)
    for x, i in enumerate(winner):
      to_update = self.getneighbor(i[0], N)
      for j in range(N+1):
        e = self.Geteta(t, j)
        for w in to_update[j]:
          self.W[:, w] = np.add(self.W[:,w], e*(X[x,:] - self.W[:,w]))

  def getneighbor(self, index, N):
    """
    :param index:获胜神经元的下标
    :param N: 邻域半径
    :return ans: 返回一个集合列表,分别是不同邻域半径内需要更新的神经元坐标
    """
    a, b = self.output
    length = a*b
    def distence(index1, index2):
      i1_a, i1_b = index1 // a, index1 % b
      i2_a, i2_b = index2 // a, index2 % b
      return np.abs(i1_a - i2_a), np.abs(i1_b - i2_b)

    ans = [set() for i in range(N+1)]
    for i in range(length):
      dist_a, dist_b = distence(i, index)
      if dist_a <= N and dist_b <= N: ans[max(dist_a, dist_b)].add(i)
    return ans



  def train(self):
    """
    train_Y:训练样本与形状为batch_size*(n*m)
    winner:一个一维向量,batch_size个获胜神经元的下标
    :return:返回值是调整后的W
    """
    count = 0
    while self.iteration > count:
      train_X = self.X[np.random.choice(self.X.shape[0], self.batch_size)]
      normal_W(self.W)
      normal_X(train_X)
      train_Y = train_X.dot(self.W)
      winner = np.argmax(train_Y, axis=1).tolist()
      self.updata_W(train_X, count, winner)
      count += 1
    return self.W

  def train_result(self):
    normal_X(self.X)
    train_Y = self.X.dot(self.W)
    winner = np.argmax(train_Y, axis=1).tolist()
    print (winner)
    return winner

def normal_X(X):
  """
  :param X:二维矩阵,N*D,N个D维的数据
  :return: 将X归一化的结果
  """
  N, D = X.shape
  for i in range(N):
    temp = np.sum(np.multiply(X[i], X[i]))
    X[i] /= np.sqrt(temp)
  return X
def normal_W(W):
  """
  :param W:二维矩阵,D*(n*m),D个n*m维的数据
  :return: 将W归一化的结果
  """
  for i in range(W.shape[1]):
    temp = np.sum(np.multiply(W[:,i], W[:,i]))
    W[:, i] /= np.sqrt(temp)
  return W

#画图
def draw(C):
  colValue = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
  for i in range(len(C)):
    coo_X = []  #x坐标列表
    coo_Y = []  #y坐标列表
    for j in range(len(C[i])):
      coo_X.append(C[i][j][0])
      coo_Y.append(C[i][j][1])
    pl.scatter(coo_X, coo_Y, marker='x', color=colValue[i%len(colValue)], label=i)

  pl.legend(loc='upper right')
  pl.show()

#数据集:每三个是一组分别是西瓜的编号,密度,含糖量
data = """
1,0.697,0.46,2,0.774,0.376,3,0.634,0.264,4,0.608,0.318,5,0.556,0.215,
6,0.403,0.237,7,0.481,0.149,8,0.437,0.211,9,0.666,0.091,10,0.243,0.267,
11,0.245,0.057,12,0.343,0.099,13,0.639,0.161,14,0.657,0.198,15,0.36,0.37,
16,0.593,0.042,17,0.719,0.103,18,0.359,0.188,19,0.339,0.241,20,0.282,0.257,
21,0.748,0.232,22,0.714,0.346,23,0.483,0.312,24,0.478,0.437,25,0.525,0.369,
26,0.751,0.489,27,0.532,0.472,28,0.473,0.376,29,0.725,0.445,30,0.446,0.459"""

a = data.split(',')
dataset = np.mat([[float(a[i]), float(a[i+1])] for i in range(1, len(a)-1, 3)])
dataset_old = dataset.copy()

som = SOM(dataset, (5, 5), 1, 30)
som.train()
res = som.train_result()
classify = {}
for i, win in enumerate(res):
  if not classify.get(win[0]):
    classify.setdefault(win[0], [i])
  else:
    classify[win[0]].append(i)
C = []#未归一化的数据分类结果
D = []#归一化的数据分类结果
for i in classify.values():
  C.append(dataset_old[i].tolist())
  D.append(dataset[i].tolist())
draw(C)
draw(D)

由于数据比较少,就直接用的训练集做测试了,运行结果图如下,分别是对未归一化的数据和归一化的数据进行的展示。

python实现SOM算法python实现SOM算法

参考内容:

1.《机器学习》周志华
2.自组织竞争神经网络SOM

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现simhash算法实例
Apr 25 Python
python检查指定文件是否存在的方法
Jul 06 Python
python 字符串转列表 list 出现\ufeff的解决方法
Jun 22 Python
对python 自定义协议的方法详解
Feb 13 Python
Python分析彩票记录并预测中奖号码过程详解
Jul 09 Python
Python中的 sort 和 sorted的用法与区别
Aug 10 Python
python实现的汉诺塔算法示例
Oct 23 Python
python中的线程threading.Thread()使用详解
Dec 17 Python
Python实现初始化不同的变量类型为空值
Jun 02 Python
使用Python绘制台风轨迹图的示例代码
Sep 21 Python
Python图像读写方法对比
Nov 16 Python
基于Python实现股票收益率分析
Apr 02 Python
python实现k-means聚类算法
Feb 23 #Python
python写一个md5解密器示例
Feb 23 #Python
Python机器学习之K-Means聚类实现详解
Feb 22 #Python
python实现远程通过网络邮件控制计算机重启或关机
Feb 22 #Python
python实现微信发送邮件关闭电脑功能
Feb 22 #Python
python使用itchat实现手机控制电脑
Feb 22 #Python
Python实现利用163邮箱远程关电脑脚本
Feb 22 #Python
You might like
重量级动漫纷纷停播!唯独OVERLORD第四季正在英魂之刃继续更新
2020/05/06 日漫
php实现水仙花数的4个示例分享
2014/04/08 PHP
php判断文件上传类型及过滤不安全数据的方法
2014/12/17 PHP
php实现excel中rank函数功能的方法
2015/01/20 PHP
PHP实现WebService的简单示例和实现步骤
2015/03/27 PHP
PHP依赖注入(DI)和控制反转(IoC)详解
2017/06/12 PHP
Avengerls vs Newbee BO3 第二场2.18
2021/03/10 DOTA
jQuery 1.0.4 - New Wave Javascript(js源文件)
2007/01/15 Javascript
js小技巧--自动隐藏红叉叉
2007/08/13 Javascript
深入理解JavaScript定时机制
2010/10/29 Javascript
Extjs中TabPane如何嵌套在其他网页中实现思路及代码
2013/01/27 Javascript
js为数字添加逗号并格式化数字的代码
2013/08/23 Javascript
一个Action如何调用两个不同的方法
2014/05/22 Javascript
nodejs开发环境配置与使用
2014/11/17 NodeJs
jquery带有索引按钮且自动轮播切换特效代码分享
2015/09/15 Javascript
EasyUI在Panel上动态添加LinkButton按钮
2017/08/11 Javascript
vue-router之nuxt动态路由设置的两种方法小结
2018/09/26 Javascript
Emberjs 通过 axios 下载文件的方法
2019/09/03 Javascript
使用IPython下的Net-SNMP来管理类UNIX系统的教程
2015/04/15 Python
Linux系统(CentOS)下python2.7.10安装
2018/09/26 Python
Python设计模式之装饰模式实例详解
2019/01/21 Python
Python 实现try重新执行
2019/12/21 Python
Python利用FFT进行简单滤波的实现
2020/02/26 Python
在python tkinter界面中添加按钮的实例
2020/03/04 Python
python GUI库图形界面开发之PyQt5信号与槽基础使用方法与实例
2020/03/06 Python
python由已知数组快速生成新数组的方法
2020/04/08 Python
阿联酋航空官方网站:Emirates
2017/10/17 全球购物
澳大利亚百货公司:David Jones
2018/02/08 全球购物
什么是三层交换,说说和路由的区别在那里
2014/09/01 面试题
Ajax请求总共有多少种Callback
2016/07/17 面试题
小学毕业家长寄语
2014/01/19 职场文书
个人对照检查材料思想汇报(四风问题)
2014/09/25 职场文书
村干部群众路线整改措施思想汇报
2014/10/12 职场文书
开会通知短信大全
2015/04/20 职场文书
社区服务活动感想
2015/08/11 职场文书
美元符号 $
2022/02/17 杂记