这里直接给出Qt代码段和演示结果。

理论部分请移步另一位博主的 自组织特征图(SOFM)详解_datamonday的博客-CSDN博客_sofm算法

算法基于 Martin H. Hagan 的《神经网络设计》 第十四章竞争网络实现。其中按照原书,使用相关性(Wp)而不是距离(||W-P||)作为获胜判定。以后将在学习向量量化(LVQ)网络中使用距离

算法改进包括:

  • 引入逐渐变小的学习步长

  • 引入墨西哥草帽函数实现“加强中心/抑制周围”

参考代码 AANN_sofm::initNeighborMatrix_MexicoStrawHat(int N)

  • 引入良心变数(conscience),并限制良心变数使用的频率

  • 使用胜出训练参数和需要调整的W(i)之间的距离来决定学习步长a,否则在实践中会发现向量很难收敛在训练数据集形成的曲面上。

(auto a = (P.transpose() - m_layer.W.row(maxIndex)).squaredNorm()/(0.01+m_layer.W.row(maxIndex).squaredNorm());)

AANN_sofm.h 文件

#ifndef AANN_SOFM_H
#define AANN_SOFM_H#include <list>
#include <vector>
#include <Eigen/Dense>
#include "QEigenExt.h"
using namespace Eigen;#include "AANN_instar.h"
/**** 自联想神经网络(Auto-Associative Neural Network , 缩写为AANN)* 是1987年Ballard提出的,其网络原型是一种具有对称拓扑结构的五层前馈传递网络,* AANN 应用到数据检验问题时具有比较明显的物理意义。是BP神经网络的一种特殊情形。* 其特点是有对称拓扑结构,即输出量等于输入量。*/
class AANN_sofm
{
public:AANN_sofm();public:
//    int GetLayerNum() const;
//    bool AppendLayer(AANN_LAYER_PARAM_F layer);virtual bool train( const Eigen::VectorXf &P, int N );virtual bool calc( const Eigen::VectorXf &P, Eigen::VectorXf *A = NULL );float getAlpha( )  const;float getGamma( )  const;long  getRound( )  const;void  setAlpha( const float alpha);void  setGamma( const float gamma);bool  setNeighborMatrix( const MatrixXf neighbors );bool  initNeighborMatrix( int N, int type );bool  initNeighborMatrix_MexicoStrawHat( int N );bool  initNeighborMatrix_Sombrero( int N );const MatrixXf getWMatrix() const;
private:void init();private:
//    AANN_LAYER_LIST_F m_layerList;AANN_LAYER_PARAM_F  m_layer;float m_alpha;float m_gamma;long  m_round;};#endif // AANN_SOFM_H

AANN_sofm.cpp文件

#include "AANN_sofm.h"#include "activation.h"
#include <iostream>
#include <time.h>
#include <stdio.h>AANN_sofm::AANN_sofm()
{m_alpha = 0.5f;m_gamma = 0.5f;init();
}void AANN_sofm::init()
{m_layer.maxB = -1;m_layer.func = hardlim;m_round = 0;
}float AANN_sofm::getAlpha( ) const
{return m_alpha;
}float AANN_sofm::getGamma( ) const
{return m_gamma;
}long AANN_sofm::getRound( )  const
{return m_round;
}void AANN_sofm::setAlpha( const float alpha)
{m_alpha = alpha;
}void AANN_sofm::setGamma( const float gamma)
{m_gamma = gamma;
}bool  AANN_sofm::setNeighborMatrix( const MatrixXf neighbors )
{if( !neighbors.size() || neighbors.rows() != neighbors.cols()){return false;}m_layer.Neighbors = neighbors;qDebug() << QString( " --------------- neighbors %1 x %2 ---------------" ).arg(neighbors.rows()).arg(neighbors.cols());for(int row=0; row<neighbors.rows(); row++  ){VectorXf r = neighbors.row(row);qDebug() << "  " << r;}return true;
}/*** @brief AANN_sofm::initNeighborMatrix*    set neighbor matris for SOFM* @param eMat*     EX: the neighbor pointers about 7 will be 2,6,8,12*          All others will be like so*          0    1    2    3    4*                    ^*          5    6 <  7  > 8    9*                    v*         10   11   12   13   14*         15   16   17   18   19*         20   21   22   23   24**    Then, neighbor Matrix will be*          0    1    2    3    4    5    6    7    8    9   10   11   12 .....       20   21   22   23   24*       +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*     0 |  1    1    0    0    0    1    0                               .....        0    0    0    0    0*     1 |  1    1    1    0    0    0    1    0                          .....        0    0    0    0    0*     2 |  0    1    1    1    0    0    0    1    0                     .....        0    0    0    0    0*     3 |  0    0    1    1    1    0    0    0    1    0                .....        0    0    0    0    0*     4 |  0    0    0    1    1    0    0    0    0    1    0           .....        0    0    0    0    0*     5 |  1    0    0    0    0    1    1    0    0    0    1    0      .....        0    0    0    0    0*     6 |  0    1    0    0    0    1    1    1    0    0    0    1    0 .....        0    0    0    0    0*     7 |       0    1    0    0    0    1*     8 |            0    1    0    0    0*     9 |                 0    1    0    0*    10 |                      0    1    0*     . |                           0    1*     . |*     . |*     . |*     . |*    22 |  0    0    0    0    0    0    0    0    0    0    0    0    0 ...          0    1    1    1    0*    23 |  0    0    0    0    0    0    0    0    0    0    0    0    0 ...          0    0    1    1    1*    24 |  0    0    0    0    0    0    0    0    0    0    0    0    0 ...          0    0    0    1    1*/
bool  AANN_sofm::initNeighborMatrix( int N, int type = 0 )
{Q_UNUSED( type );if( N <= 0 || N > 10000 ){return false;}MatrixXf neighbor = MatrixXf::Identity( N*N, N*N ) - MatrixXf::Ones( N*N, N*N )/((N+4)*(N+4));for( int row = 0; row < N*N; row++){int x = row%N;int y = row/N;if( (y+N-1)%N < y ){neighbor( ((y+N-1)%N)*N+x,         row ) = 1.f/((N+1)*(N+1));}if( (y+1)%N >y ){neighbor( ((y+1)%N)*N+x,           row ) = 1.f/((N+1)*(N+1));}if( (x+N-1)%N < x ){neighbor(           row, y*N+(x+N-1)%N ) = 1.f/((N+1)*(N+1));}if( (x+1)%N > x ) {neighbor(           row,   y*N+(x+1)%N ) = 1.f/((N+1)*(N+1));}}return setNeighborMatrix( neighbor );
}bool  AANN_sofm::initNeighborMatrix_MexicoStrawHat( int N )
{if( N <= 0 || N > 10000 ){return false;}MatrixXf neighbor = MatrixXf::Identity( N*N, N*N );for( int row = 0; row < N*N; row++)for( int col = row+1; col < N*N; col++){int dx = row%N - col%N;int dy = row/N - col/N;float d1 = 1+dx*dx+dy*dy;float d2 = (dx*dx+dy*dy)*d1*d1;neighbor( row, col ) = neighbor( col, row ) = (1.0f/d2 - 0.07f)/d1;}return setNeighborMatrix( neighbor );
}/*** @brief AANN_sofm::initNeighborMatrix_Sombrero*  refer to https://baike.baidu.com/item/Sombrero%20function/16550687* @return*/
bool  AANN_sofm::initNeighborMatrix_Sombrero( int N )
{if( N <= 0 || N > 10000 ){return false;}MatrixXf neighbor = 0.98*MatrixXf::Identity( N*N, N*N );for( int row = 0; row < N*N; row++)for( int col = row+1; col < N*N; col++){int dx = row%N - col%N;int dy = row/N - col/N;float d2 = dx*dx+dy*dy;float d1  = sqrt( d2 );float d4 = exp(2*d2);
//        float cc =  cos( (3.14f/2-0.1)*d1 );
//        float dd = cc/d4;neighbor( row, col ) = neighbor( col, row ) = cos( (3.14159/2-0.01)*d1 )/d4;}return setNeighborMatrix( neighbor );
}const MatrixXf AANN_sofm::getWMatrix() const
{return m_layer.W;
}
/*** @brief AANN_sofm::train* @param P     measured vector : 可度量特征信息:如形状,味道,温度,颜色,重量等* @param T     感知的结果,或期望的结果* @return*/
bool AANN_sofm::train( const Eigen::VectorXf &P, int S )
{const int R = P.rows();/* return false if input Dim is different */if( S <= 0 ){return false;}/* return false if input Dim is different */if( ( m_layer.W.cols() > 0 ) && ( m_layer.W.cols() != R ) ){return false;}/* return false if output Dim is different */if( ( m_layer.W.rows() > 0 ) && ( m_layer.W.rows() != S ) ){return false;}if( m_layer.Neighbors.size() && (m_layer.Neighbors.rows() != S || m_layer.Neighbors.cols() != S )){return false;}if( S != m_layer.W.rows() || R != m_layer.W.cols() ){srand( time(NULL) );m_layer.W = MatrixXf::Random( S, R );m_layer.Conscience = VectorXf::Ones( S );}int maxIndex;m_layer.N = (m_layer.W * P).array() + R;/*** @brief round_mask*        随着训练次数增长,应用良心的间隔越来越大,但总是有机会使用*         M = 3 时*           m_round  :   0~7          8~15            16~31          32~63     ...   2^(n+3) ~ 2^(n+3)-1*                 N  :    0             1               2              4       ...       2^n*         round_mask : 0x...FFFFF       1               3              7       ...       (2^(n+1))-1*   apply conscience :    8 x          8 x             8 x            8 x      ...       8 x*         M = 6 时*           m_round  :   0~63        64~127         128~255         256~511    ...   2^(n+6) ~ 2^(n+6)-1*                 N  :    0             1               2              4       ...       2^n*         round_mask : 0x...FFFFF       1               3              7       ...       (2^(n+1))-1*   apply conscience :    64 x        64 x             64 x           64 x     ...       64 x**      应用良心的频率随 M 的增加而呈指数增加,测试中 M=3 能得到比较好的性能*/static int round_mask = 1;int N = m_round >> 3;if( 0 == ( N&(N-1) ) ){round_mask = (N<<1)-1; // 0,1,2,4,8,16,...}if( 0 == ( m_round & round_mask ) ){(m_layer.N.array() * m_layer.Conscience.array()).maxCoeff(&maxIndex);} else {m_layer.N.maxCoeff(&maxIndex);}m_layer.A = VectorXf::Zero(S);m_layer.A[maxIndex] = 1;m_layer.Conscience = m_layer.Conscience.array()/(1+m_layer.A.array()).array();m_layer.Conscience.normalize();VectorXf vecA;if( m_layer.Neighbors.rows() == S ){
//        vecA = ( m_layer.Neighbors * m_layer.A ).unaryExpr(std::ref(satlin<float>));vecA = (m_layer.Neighbors * m_layer.A).normalized();} else {vecA = m_layer.A;}/**  delta W = W(q) - W(q-1) = alpha * A(q) * P(q) - gamma * A(q).diagonal * W(q-1)*/auto a = (P.transpose() - m_layer.W.row(maxIndex)).squaredNorm()/(0.01+m_layer.W.row(maxIndex).squaredNorm());a = fmin( 1.0, fmax( a, m_alpha ));m_layer.deltaW = a * vecA * P.transpose() - a * vecA.asDiagonal() * m_layer.W;m_layer.W = (m_layer.W + m_layer.deltaW);//.rowwise().normalized();m_round++;return true;
}/*** @brief AANN_sofm::calc* @param P     measured vector : 可度量特征信息:如形状,味道,温度,颜色,重量等* @return*/
bool AANN_sofm::calc( const Eigen::VectorXf &P, Eigen::VectorXf *A )
{AANN_LAYER_PARAM_F layer = m_layer;Eigen::VectorXf e;const int R = P.rows();/* return false if input Dim is different */if( ( m_layer.W.cols() <= 0 ) || ( m_layer.W.cols() != R ) ){qWarning() << QString( __FUNCTION__ " : Error! input dim  is different : expect %1, but input data is %2 " ).arg(m_layer.W.cols()).arg( R );return false;}qDebug() << __FUNCTION__ " --- CALC -----------------------";qDebug() << __FUNCTION__ " P = " << P.eval() ;m_layer.A = (m_layer.W * P).unaryExpr(std::ref(m_layer.func));qDebug() << __FUNCTION__ " A = " << m_layer.A;if( A ) {   *A = m_layer.A;   }return true;
}

线程执行代码段:


void DataWorker::on_start()
{for(int k = 0; !m_bUserQuit && (k < 100000); k++ )  //    while( false == m_bUserQuit ){updateNnData();QThread::msleep(10);}
}#define N 3void DataWorker::reset()
{m_sofm.initNeighborMatrix_Sombrero(N);
}void DataWorker::updateNnData( )
{QMutexLocker locker( &m_nnLocker );float r = sqrt(m_sofm.getRound()) ;float alpha = (r+500.0f)/( 100*r+1000.0f);m_sofm.setAlpha( alpha );m_sofm.setGamma( alpha );#define PI  3.14159265358979{float a = - acos(sqrt( (rand() % 257) / 256.0001)); // -3.14 * (rand() % 256) / 512.0;float b = PI * (rand() % 12345) / 1000.0;VectorXf P(3);P << cos(a)*sin(b), sin(a), cos(a)*cos(b);if(m_trainSetModel && ( m_sofm.getRound() < 10000) ){
//            WData d(cos(a)*sin(b), cos(a)*cos(b), sin(a));m_trainSetModel->append( WData(P[0],P[1],P[2]));m_trainSetModel->dataChanged( m_trainSetModel->index(0,0), m_trainSetModel->index(-1,-1));}m_sofm.train( P, N*N );}m_dataModel->update(m_sofm.getWMatrix());}

以下是36点在半球形中的演示结果

以下是9点在半球形中的演示结果。看得出,用距离来决定学习步长在这时造成了结果的发散

演示代码

自组织特征图SOFM网络的实现相关推荐

  1. 基因表达聚类分析之初探SOM - 自组织特征图

    之前的培训有老师提出要做SOM分析,最后卡在code plot只能出segment plot却出不来line plot.查了下,没看到解决方案.今天看了下源码,设置了一个参数,得到趋势图.也顺便学习了 ...

  2. som神经网络聚类简单例子_基因表达聚类分析之初探SOM - 自组织特征图

    之前的培训有老师提出要做SOM分析,最后卡在code plot只能出segment plot却出不来line plot.查了下,没看到解决方案.今天看了下源码,设置了一个参数,得到趋势图.也顺便学习了 ...

  3. FPN:特征图金字塔网络

    1. 论文简介 论文名:Feature Pyramid Networks for Object Detection 论文地址 :FPN 论文作者:Tsung-Yi Lin, Piotr Dollar, ...

  4. FPN(特征图金字塔网络)理论基础与具体实现

    论文地址:Feature Pyramid Networks for Object Detection 项目地址:FPN_pytorch 0x00 前言 我们在做目标检测和超分辨率重建等问题的时候,我们 ...

  5. 机器学习 竞争神经网络与自组织特征映射神经网络(SOFM)

    本文按照 案例-分析-代码-原理 四段式进行介绍,为便于有一定理论基础的童鞋进行学习,将原理以链接其他博客的形式给出,有兴趣的童鞋可以跳转进行学习和推敲. [案例介绍]利用竞争神经网络和自组织特征隐射 ...

  6. 卷积神经网络特征图可视化及其意义

    文章目录 特征图可视化方法 1. tensor->numpy->plt.save 2. register_forward_pre_hook函数实现特征图获取 3. 反卷积可视化 特征图可视 ...

  7. 卷积神经网络的特征图可视化

    原图: Keras代码: from keras.models import Sequential from keras.layers.convolutional import Convolution2 ...

  8. 利用ANN作图——自组织特征映射网络(SOFM)探究及实现

    利用ANN作图--自组织特征映射网络(SOFM)探究及实现 在研究生的<人工智能>课堂上学习了利用人工神经网络(ANN)解决问题的基本思想与方法,在学习了自组织特征映射网络(SOFM)之后 ...

  9. 自组织特征映射(SOFM或SOM)网络解决旅行商问题(TSP)

    自组织特征映射(Self-Organizing Feature Map)网络介绍: 由输入层,输出层神经元节点构成的神经网络(由输入层,隐层神经元节点构成的神经网络) 无监督学习 学习准则是胜者为王学 ...

最新文章

  1. oracle show选项,Oracleshowparameter命令的小技巧有哪些呢?
  2. 缘何Square可以在移动支付领域上成功?
  3. python中加入绝对路径_理解Python中的绝对路径和相对路径
  4. android 多个复选框,Android UI控件之CheckBox(复选框、多选框)
  5. Linux下C语言使用openssl库进行MD5校验
  6. hadoop设置java环境_hadoop安装(3)_Linux配置JDK环境
  7. 3. 什么是icmp?icmp与ip的关系_公共关系与人际交往能力自主模式课程相关
  8. CentOS7.2 在线安装MySQL8.0
  9. keras模型训练参数
  10. Atitit. 构造ast 语法树的总结attilax v2 q0f
  11. 图扑软件以轻量化建模构建智慧城市
  12. Cookie、Session 简述
  13. 理解RoIAlign实际操作
  14. 坚果pro android版本,坚果Pro有几个版本 哪个版本好?坚果Pro各版本的区别
  15. APP加密,ios代码混淆工具,虚拟化技术 适用于移动应用程序的虚拟化加密软件
  16. AutoCAD正版软件多少钱?企业应该采购多少license?
  17. js模糊匹配(like)
  18. Dark GDK 初体验
  19. 线上docker服务频繁自动重启解决过程
  20. K-Means集群算法

热门文章

  1. CAN诊断的寻址方式
  2. Word处理控件Aspose.Words功能演示:使用 Java 比较 MS Word 文档
  3. 怎样策划微博营销方案
  4. 抖音四面被拒,再战头条终获offer,系列教学
  5. IDEA如何导入多个maven项目在pox引入自建包
  6. M1 docker 安装mysql5.7
  7. matlab中暂停的快捷键,如何设置“暂停调用”和“强制调用”快捷键
  8. Slicer学习笔记(二十一)slicer的python接口说明
  9. (NXP)LS1012 LS1043 LS1046 LS1028 性能PK对比-飞凌嵌入式
  10. 小电流选线装置的研制之