SOM模型
姓名:闫伟 学号:15020150038
转载自:https://www.zhihu.com/question/28046923/answer/499882606
【嵌牛导读】:SOM 即自组织映射,是一种用于特征检测的无监督学习神经网络。它模拟人脑中处于不同区域的神经细胞分工不同的特点,即不同区域具有不同的响应特征,而且这一过程是自动完成的。SOM 用于生成训练样本的低维空间,可以将高维数据间复杂的非线性统计关系转化为简单的几何关系,且以低维的方式展现,因此通常在降维问题中会使用它。
【嵌牛鼻子】:SOM 特征检测 无监督学习
【嵌牛提问】:SOM是怎样一种模型(对于初学者如何操作,算法等)?
【嵌牛正文】:
SOM 与其它人工神经网络不同,因为它们使用的是竞争性学习而不是错误相关的学习,后者涉及到反向传播和梯度下降。在竞争性学习中,各个节点会相互竞争响应输入数据子集的权利。训练数据通常没有标签,映射会学习根据相似度来区分各个特征。
SOM 的工作原理
下图展示了 SOM 的训练过程。紫色区域表示训练数据的分布状况,白色网格表示从该分布中提取的当前训练数据。首先,SOM 节点位于数据空间的任意位置。最接近训练数据的节点(黄色高亮部分)会被选中。它和网格中的邻近节点一样,朝训练数据移动。在多次迭代之后,网格倾向于近似该种数据分布(下图最右)。
当我们将训练数据输入到网络中时,会计算出所有权重向量的欧几里德距离。权重向量与输入最相似的神经元称为最佳匹配单元(BMU)。BMU 的权重和 SOM 网格中靠近它的神经元会朝着输入矢量的方向调整。一旦确定了 BMU,下一步就是计算其它哪些节点在 BMU 的邻域内。
自组织的组成部分
初始化:将所有连接权重初始化为随机值。
竞争:输出节点相互竞争激活的机会,每次只有一个被激活。激活的神经元就叫做“赢家通吃”神经元。由于存在这种竞争,神经元被迫自我组织,形成自组织映射(SOM)。
合作:在竞争中获胜的神经元会决定活跃神经元拓扑邻域的空间位置,为相邻神经元之间的合作提供了基础。
适应:活跃神经元会降低判别函数的个体值,通过适当调整相关连接权重来完成(和输入模式相关)。这样,获胜神经元对随后应用同样输入模式的响应就会得到增强。判别函数定义为每个神经元j的输入向量x和权重向量wj之间的平方欧几里德距离:
训练 SOM 的步骤
训练 SOM 涉及以下几步:
初始化每个节点的权重。权重设置为标准化小型随机值。
从训练集中随机选择一个向量并呈现给网格。
检查每个节点来计算哪一个的权重最像输入向量。这会让你获得最佳匹配单元(BMU)。我们通过迭代所有节点并计算每个节点的权重与当前输入向量之间的欧几里德距离来计算BMU。权重向量和输入向量最接近的节点则被标记为BMU。
计算BMU邻域的半径。在半径范围内找到的节点则认为处于BMU邻域内。
调整在步骤4中发现的节点的权重,让它们更像输入向量。节点和BMU越近,权重调整的越多。
重复步骤2,迭代N次。
SOM 的应用
SOM 通常用在可视化中。比如下图,世界各国贫困数据的可视化。生活质量较高的国家聚集在左上方,而贫困最严重的国家聚集在右下方。
SOM 的其它一些应用还包括:
数据压缩
语音识别
分离音源
欺诈检测
MiniSom 简介
MiniSom 基于 Numpy,以简约的风格实现了 SOM。通过 pip 就可以下载 MiniSom:
pip install minisom
如何使用 MiniSom?
如果想使用 MiniSom,你的数据必须组织为 Numpy 数组的形式,用行表示一个观察值。
data = [[ 0.80, 0.55, 0.22, 0.03],[ 0.82, 0.50, 0.23, 0.03],[ 0.80, 0.54, 0.22, 0.03],[ 0.80, 0.53, 0.26, 0.03],[ 0.79, 0.56, 0.22, 0.03],[ 0.75, 0.60, 0.25, 0.03],[ 0.77, 0.59, 0.22, 0.03]]
待数据集设置好后,就可以按照如下方式实现 MiniSom。第一步是在安装 MiniSom 后导入 MiniSom 类。
from minisom import MiniSom
接着,我们可以以 0.5 的学习率来初始化一个 6*6 的 SOM。
som = MiniSom(6, 6, 4, sigma=0.3, learning_rate=0.5)Then we train the SOM on 100 iterations.som.train_random(data, 100)
MiniSom 实现了两类训练:train_random 和 train_batch。在 train_random 中,我们通过从数据中选择随机样本来训练模型。在 train_batch 中,按照样本的存储顺序来选择它们。使用 random_weights_init 方法,通过从数据中选择随机样本来初始化权重。
用 MiniSom 创建一个简单的 SOM
现在我们使用所学的知识来创建一个简单的颜色量化模型。颜色量化就是减少图像中所用的特殊颜色,并且让得到的新图像尽可能地从视觉上和原图像相似。当我们在只能显示有限数量的颜色的设备上展示具有更多颜色的图像时,颜色量化就有很大的用途。如果内存有限,难度就更大了。我们下面就搭建一个模型,可以学习一张房屋图像中的颜色,然后用学到的知识来重构原图像。
第一步是从 MiniSom 中导入 MiniSom 类,以及 Numpy 和 matplotlib。如果你用的是 Jupyter,需要在代码行中包含 %matplotlib 来查看 notebook 中的图像。
from minisom import MiniSomimport numpy as npimport matplotlib.pyplot as plt%matplotlib inline
加载图像
之前提到过,MiniSom 是基于 Numpy 实现的 SOM,因此我们必须将图像加载为一个数组。可以使用 matplotlib 的 imread 实用程序来完成。
img = plt.imread('house.jpg')
可以用 matplotlib 中的 imshow 函数来查看加载后的图像。
plt.imshow(img)
我们检查一下加载后的图像形状。
可以看到它是一个 3D 矩阵,我们需要乘以 730 和 1368 将数组转换为一个 2D 数组,如下所示。在这之后,我们用 Numpy 的 shape 属性来检查它的形状。
pixels = np.reshape(img, (img.shape[0]*img.shape[1], 3))
SOM 初始化和训练
我们初始化 MiniSom 对象并将其分配给变量 som。它采用的第一个参数是 SOM 的维度。在我们的例子中,我们将构建一个 3*3 的 SOM。这意味着我们得到的最终颜色将是 3 * 3,即 9。这里的数字可以随意尝试,看看你会得到哪些不同的结果。显然,SOM 越大,训练所需的时间就越长。
第二个参数是 input_len,它是我们数据集中的特征数量。在我们的例子中,我们使用 3,对应了像素数组的形状。如果你使用其它数字,会得到一个值错误异常,指示 MiniSom 无法将形状(3)中的输入数组发送到你选择的数字中。
下一个参数是 sigma,它是 SOM 中不同相邻节点的半径,默认值为 1.0。
最后一个参数是 learning_rate,它确定每次迭代期间权重的调整幅度。经过几次实验,发现 sigma 为 0.1,学习率为 0.2,会得到一些不错的结果。
som = MiniSom(x= 3, y = 3, input_len = 3, sigma=0.1, learning_rate=0.2)
下一步是将SOM的权重初始化为小的标准化随机值。我们使用random_weights_init函数并传入我们的数据(像素)来实现这一点。
som.random_weights_init(pixels)
我们现在需要保存起始权重,它们代表图像的初始颜色。稍后会将它们可视化。我们保存这些权重的方法是使用 get_weights 函数和 Python 的副本来确保在权重更新之前得到它们。
starting_weights = som.get_weights().copy()
然后我们通过运行 train_random 函数来训练像素。它需要两个参数,第一个参数是需要训练的数据集,第二个参数是迭代次数。
som.train_random(pixels, 100)
向量量化
下一步是量化图像的每个像素。在此过程中,我们将减少图像中的颜色数量。我们使用 MiniSom 中的 quantization 实用程序来完成这一步。
qnt = som.quantization(pixels)
创建新图像
如果你还记得,在这个过程的开始我们必须将图像转换成 2D 数组。但是,现在我们需要将图像构建为 3D 图像。可以用我们在开头加载的图像维度创建一个只有零的矩阵来完成这项工作。借助 Numpy 的 zero 实用程序,我们可以轻松完成这项工作。
clustered = np.zeros(img.shape)
接下来我们需要做的是将量化后的值放入新图像中。为此,我们使用 Numpy 的 unravel_index 功能。这个函数有三个参数:
indices:array_like
一个整数数组,其元素是维度变暗数组的平铺版本的索引。
dims:整数元组
用于解开 indices.dex 值的数组的形状:
Order:{'C','F'},可选
确定是否应将索引视为以行主(C样式)或列主(Fortran样式)顺序编制索引。
for i, q in enumerate(qnt): clustered[np.unravel_index(i, dims=(img.shape[0], img.shape[1]))] = q
显示结果
Matplotlib 能让我们用 imshow 在轴上绘制图像。我们使用一个 Matplotlib 图和 4 个子图来完成绘图。第一个和第二个子图将显示原始图像和新图像。第三和第四个子图将显示初始图像颜色和 SOM 学习的颜色。
我们创建一个 12*6 的图像。然后我们创建子图,它有 3 个参数:行数,列数和图索引。当这些数字小于 10 时,可以作为三位数传递,如下所示。然后我们使用 Matplotlib 的 imshow 来绘制图像。
plt.figure(figsize=(12, 6))plt.subplot(221)plt.title('Original')plt.imshow(img)plt.subplot(222)plt.title('Result')plt.imshow(clustered)
我们以类似的方式创建第三和第四个子图。
plt.subplot(223)plt.title('Initial Colors')plt.imshow(starting_weights)plt.subplot(224)plt.title('Learnt Colors')plt.imshow(som.get_weights())
我们使用 tight_layout 功能来确保我们的绘图不会挤在一起。最后,我们使用 plt.show()绘制它们。
plt.tight_layout()plt.show()
就这样我们搭建了一个 SOM 网络,能够完成颜色量化任务,重构原图像。
结语
本文我们讨论了 SOM 的含义及其工作原理,并用 MiniSom 实现了一个简单 SOM 模型。值得一提的是,在我们涉及 SOM 的工作中,MiniSom 是个不错的工具,可用于基于 SOM 的欺诈检测和机器人开发的任务中,均取得不俗的成绩。