自组织特征映射网络[Python代码实现]

断水流大师兄 2018-06-06 10:12
关注文章

  接上一篇自组织特征映射网络,在均匀分布的数据上,用Python实现SOM,用SOM解决网格动力学问题.用一个二维的分布驱动一个二维的网格.使用数据仿真来说明SOM算法的行为,使用100个神经元组成的网络,排列成10*10的网格,用二维向量x 进行网络的训练,x是一组均匀分布在[0,1]之间的数据集合,网络的权值为均匀分布在[-0.1,0.1]之间随机数集合.

# 由二维分布驱动一个二维的网络
# 输出层网络的大小有 H*W,个神经元组成
# 训练数据为二维向量,分量x1,x2均匀分布在{-1,+1}之间
import numpy as np
import matplotlib.pyplot as plt

网络参数

# 网络的输出网格的高,宽
H = 10.0
W = 10
M = 40000    # 迭代的次数

生成训练数据

# 均匀分布的训练数据 x
x = np.random.uniform(0,1,(2000,2))
plt.figure(figsize=(12,6))
plt.scatter(x[:,0],x[:,1],s=6)
plt.show()

description

辅助函数

# 网络的辅助函数
# 欧式距离,返回一个数组
def distEclud(x, weights):
    dist = []
    for w in weights:
        d = np.linalg.norm(x-w)
        dist.append(d)
    return np.array(dist)
        
# 输出层网格的初始化(每个节点制定网格中的坐标)
# h,w 分别是输出层网格的高和宽
def init_grid(h,w):
    k = 0
    grid = np.zeros((h*w, 2))
    for i in range(h):
        for j in range(w):
            grid[k,:] = [i,j]
            k = k+1
    return grid

# 网络权值的初始化
# 权值向量的维度和向量的维度是相等的
def init_weights(h, w):
    # h,网格的高
    # w,网格的宽
    weights = np.random.uniform(-0.1,0.1,(h*w, 2))
    return weights

# 拓扑邻域半径衰减函数
def radius(n, t, r_0):
    # n是迭代的次数
    # t是一个时间常数
    # r_0 是半径的初始值,一般为网格的半径
    return r_0 * np.exp(-n / (t/np.log(r_0)))

# 学习效率的衰减函数
def learn_rate(n, t, r_0):
    # n 迭代的次数
    # t 一个常数
    # r_0 初始的学习效率
    return r_0 * np.exp(-n / (t/np.log(5.0)))

初始化网络

# 初始化
grid = init_grid(int(H), W)       # 网格为10,10二维网格
weights = init_weights(int(H), W)

# 初始权值可视化
%matplotlib inline 
plt.figure(figsize=(12,6))
plt.scatter(weights[:,0], weights[:,1],s=6)
plt.xlim(-1,1)
plt.ylim(-1,1)

 

description

训练网络

rads = []    # 记录半径的变化值
rates = []   # 记录学习效率的变化

for n in xrange(40000):
    r = radius(n, 4000, 6.0)
    rate = learn_rate(n, 4000, 0.1)
    rads.append(r)
    rates.append(rate)
    
    # 随机选择一个向量x
    k = np.random.randint(0,len(x))
    sample = x[k,:]
    
    # 根据最距离小化原则,找到获胜神经元
    # 计算每个权值向量与x的欧几里得距离
    dists = distEclud(sample, weights)  
    index = dists.argmin()
    
    # 计算获胜神经元在输出网格中的位置(坐标)
    # ceil() 返回大于输入值的整数
    d1 = np.ceil(index / H)
    d2 = np.mod(index , H)
    
    # 计算网格中其他神经元到激活神经元的侧向距离
    dist2 = distEclud(np.array([d1, d2]), grid)
    # 获取拓扑邻域有效半径内的神经元索引
    # dist2 < r,得到一个布尔值数组
    # nonzero()返回数组中为真的索引
    index2 = (dist2 < r).nonzero()[0]
    
    # 更新拓扑邻域,有效半径内神经元的权值
    for j in index2:
        weights[j,:] = weights[j,:] + rate*(sample - weights[j,:])
    
    # 记录部分权值
    if n == 500:
        w_5 = weights.copy()
    if n == 10000:
        w_10k = weights.copy()
     
    if n % 10000 == 0:
        print '%d0k is over'%(n/10000)

半径变化曲线

%matplotlib inline 
plt.figure(figsize=(12,5))
plt.grid(True)
plt.plot(rads)

 

description

学习效率曲线

%matplotlib inline 
plt.figure(figsize=(12,5))
plt.grid(True)
plt.plot(rates)

description 可视化方法

# 可视化方法
def scat_weights(weights,size=(6,6)):
    plt.figure(figsize=size)
    plt.scatter(weights[:,0], weights[:,1],s=6)
    
def plot_weights(weights, h=10, w=10, size=(6,6)):
    x_axis = weights[:,0].reshape(h, w)
    y_axis = weights[:,1].reshape(h, w)
    plt.figure(figsize=size)    
    for i in range(h):
        plt.plot(x_axis[i], y_axis[i])
        plt.plot(x_axis.T[i], y_axis.T[i])

 description

description

description

文章被以下专辑收录
推荐阅读

异常检测[Keras]

{{panelTitle}}
支持Markdown和数学公式,公式格式:\\(...\\)或\\[...\\]

还没有内容

关注微信公众号