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中使用glob和rmtree删除目录子目录及所有文件的例子
Nov 21 Python
Django中传递参数到URLconf的视图函数中的方法
Jul 18 Python
在Ubuntu系统下安装使用Python的GUI工具wxPython
Feb 18 Python
python 数字类型和字符串类型的相互转换实例
Jul 17 Python
python将.ppm格式图片转换成.jpg格式文件的方法
Oct 27 Python
python 同时运行多个程序的实例
Jan 07 Python
如何基于Python实现自动扫雷
Jan 06 Python
PyTorch 普通卷积和空洞卷积实例
Jan 07 Python
TensorFLow 不同大小图片的TFrecords存取实例
Jan 20 Python
Pytorch 使用CNN图像分类的实现
Jun 16 Python
pytorch中的model.eval()和BN层的使用
May 22 Python
Python装饰器详细介绍
Mar 25 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
改进的IP计数器
2006/10/09 PHP
PHP中Date获取时间不正确怎么办
2008/06/05 PHP
php判断字符串在另一个字符串位置的方法
2014/02/27 PHP
php采用curl访问域名返回405 method not allowed提示的解决方法
2014/06/26 PHP
ThinkPHP使用smarty模板引擎的方法
2014/07/01 PHP
Thinkphp 框架扩展之行为扩展原理与实现方法分析
2020/04/23 PHP
javascript学习(一)构建自己的JS库
2013/01/02 Javascript
禁用Tab键JS代码兼容Firefox和IE
2014/04/18 Javascript
鼠标悬浮停留三秒后自动显示大图js代码
2014/09/09 Javascript
JQuery实现的图文自动轮播效果插件
2015/06/19 Javascript
谈谈JavaScript自定义回调函数
2015/10/18 Javascript
angularJS+requireJS实现controller及directive的按需加载示例
2017/02/20 Javascript
node.js程序作为服务并在windows下开机自启动(用forever)
2017/03/29 Javascript
mpvue开发音频类小程序踩坑和建议详解
2019/03/12 Javascript
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
2019/05/10 Javascript
微信小程序中为什么使用var that=this
2019/08/27 Javascript
vue基础知识--axios合并请求和slot
2020/06/04 Javascript
[39:32]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS DT 第二场
2014/05/23 DOTA
[01:01:04]2018DOTA2亚洲邀请赛 4.5 淘汰赛 OpTic vs TNC 第一场
2018/04/06 DOTA
Python实现的爬取网易动态评论操作示例
2018/06/06 Python
python与caffe改变通道顺序的方法
2018/08/04 Python
Python对excel文档的操作方法详解
2018/12/10 Python
wxpython绘制圆角窗体
2019/11/18 Python
荷兰多品牌网上鞋店:Stoute Schoenen
2017/08/24 全球购物
应届生船舶驾驶求职信
2013/10/19 职场文书
毕业生应聘幼儿园的自荐信
2013/11/20 职场文书
商场端午节活动方案
2014/01/29 职场文书
爱与责任演讲稿
2014/05/20 职场文书
工艺技术员岗位职责
2015/02/04 职场文书
培训师岗位职责
2015/02/14 职场文书
2015年普法依法治理工作总结
2015/05/26 职场文书
2016年感恩教师节活动总结
2016/04/01 职场文书
纪念建国70周年演讲稿
2019/07/19 职场文书
tensorboard 可视化之localhost:6006不显示的解决方案
2021/05/22 Python
Python基础之条件语句详解
2021/06/16 Python
win10重装系统后上不了网怎么办 win10重装系统网络故障的解决办法
2022/07/23 数码科技