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脚本实现统计日志文件中的ip访问次数代码分享
Aug 06 Python
Python的Flask框架中实现登录用户的个人资料和头像的教程
Apr 20 Python
自动化Nginx服务器的反向代理的配置方法
Jun 28 Python
flask框架实现连接sqlite3数据库的方法分析
Jul 16 Python
对sklearn的使用之数据集的拆分与训练详解(python3.6)
Dec 14 Python
python实现随机漫步方法和原理
Jun 10 Python
Django用户认证系统 User对象解析
Aug 02 Python
对Django中内置的User模型实例详解
Aug 16 Python
Python 面向对象之类class和对象基本用法示例
Feb 02 Python
增大python字体的方法步骤
Jul 05 Python
学python爬虫能做什么
Jul 29 Python
利用Selenium添加cookie实现自动登录的示例代码(fofa)
May 08 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
php4的彩蛋
2006/10/09 PHP
PHP面向对象之后期静态绑定功能介绍
2015/05/18 PHP
php中session定期自动清理的方法
2015/11/12 PHP
用javascript实现分割提取页面所需内容
2007/05/09 Javascript
在线编辑器中换行与内容自动提取
2009/04/24 Javascript
js如何判断不同系统的浏览器类型
2013/10/28 Javascript
JavaScript中检测变量是否存在遇到的一些问题
2013/11/11 Javascript
前台js对象在后台转化java对象的问题探讨
2013/12/20 Javascript
浅谈javascript中createElement事件
2014/12/05 Javascript
Javascript优化技巧之短路表达式详细介绍
2015/03/27 Javascript
jQuery焦点图插件SaySlide
2015/12/21 Javascript
javaScript数组迭代方法详解
2016/04/14 Javascript
前端js文件合并的三种方式推荐
2016/05/19 Javascript
BootStrap 智能表单实战系列(十)自动完成组件的支持
2016/06/13 Javascript
Vue中的Vux配置指南
2017/12/08 Javascript
vue和webpack打包项目相对路径修改的方法
2018/06/15 Javascript
jQuery实现的简单拖拽功能示例【测试可用】
2018/08/14 jQuery
关于AngularJS中ng-repeat不更新视图的解决方法
2018/09/30 Javascript
跟老齐学Python之网站的结构
2014/10/24 Python
收藏整理的一些Python常用方法和技巧
2015/05/18 Python
使用python遍历指定城市的一周气温
2017/03/31 Python
python使用筛选法计算小于给定数字的所有素数
2018/03/19 Python
python字典值排序并取出前n个key值的方法
2018/10/17 Python
简单了解python中对象的取反运算符
2019/07/01 Python
python3 requests库实现多图片爬取教程
2019/12/18 Python
Python环境使用OpenCV检测人脸实现教程
2020/10/19 Python
python eventlet绿化和patch原理
2020/11/21 Python
如何进行Linux分区优化
2013/02/12 面试题
自荐信格式范文
2013/10/07 职场文书
财务管理专业推荐信
2013/11/19 职场文书
优秀教师的感人事迹
2014/02/04 职场文书
应届生求职信
2014/05/31 职场文书
2014学习优秀共产党员先进事迹思想汇报
2014/09/14 职场文书
医院2014国庆节活动策划方案
2014/09/21 职场文书
2015年共青团工作总结
2015/05/15 职场文书
小学作文指导之如何写人?
2019/07/08 职场文书