【原创】python实现RBF神经网络识别Mnist数据集

2020/11/18 08:31
阅读数 95

版权声明:本文为博主ExcelMann的原创文章,未经博主允许不得转载。

python实现RBF神经网络识别Mnist数据集

作者:ExcelMann,转载需注明。

话不多说,直接贴代码,代码有注释。

# Author:Xuangan, Xu
# Data:2020-11-11

"""
RBF神经网络
-----------------
设计RBF神经网络实现手写数字的识别问题
数据集:Mnist数据集
"""

import os
import struct
import math
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from scipy import *
from scipy.linalg import norm, pinv
from sklearn.cluster import KMeans

class RBFNet:

    def __init__(self,sample_num,input_nodes,hidden_nodes,output_nodes):
        # 初始化网络各层结点个数
        self.i_nodes = input_nodes  # 即每个样本的维数
        self.h_nodes = hidden_nodes # 即中心点个数
        self.o_nodes = output_nodes

        # 初始化中心节点、方差、权重以及矩阵G(G[i][j]表示第i个样本在第j个中心节点的高斯函数值)
        self.centers = [random.uniform(-1,1,input_nodes) for i in range(hidden_nodes)]
        self.beta = 0
        self.w = random.uniform(-0.5,0.5,(hidden_nodes,output_nodes))
        self.G = np.zeros((sample_num,hidden_nodes))

    def culMse(self,pre_y,y):
        """
        计算均方误差
        :param pre_y: 预测值(60000 X 10)
        :param y: 期望值(60000 X 10)
        """
        totalError = 0
        for i in range(len(y)):
            for j in range(10):
                totalError += (y[i][j]-pre_y[i][j])**2
        return totalError/len(y)

    def calBasis(self,X,Xi):
        """
        计算隐含层结点值
        :param X:输入值,大小为维度
        :param Xi:第i个中心点,大小为维度
        :return:返回该隐含层结点的值
        """
        return exp((-np.linalg.norm(X-Xi)**2)/2*self.beta**2)

    def calHiddenValue(self,X):
        """
        计算矩阵G
        :param X:输入样本X
        """
        for ci,c in enumerate(self.centers):
            for xi,x in enumerate(X):
                self.G[xi][ci] = self.calBasis(c, x)

    def train(self,X,Y):
        """
        训练网络,由闭式解得到网络权重w
        :param X:输入样本X,大小为(样本个数, 784)
        :param Y:标签数据Y,大小为(样本个数,10)
        """
        # 选择中心点
        estimator = KMeans(n_clusters=1000)  # 划分为1000类
        estimator.fit(X)
        self.centers = estimator.cluster_centers_  # 得到1000个类别的各自中心点
        # 更新方差beta
        max_distance = 0  # 所选取中心之间的最大距离
        for i in range(self.h_nodes):
            for j in range(self.h_nodes-i):
                dis = np.linalg.norm(self.centers[i]-self.centers[j])
                if(dis > max_distance):
                    max_distance = dis
        self.beta = max_distance/sqrt(2*self.h_nodes)
        # 计算矩阵G
        self.calHiddenValue(X)
        # 由闭式解,得到网络权重w
        self.w = dot(pinv(dot(self.G.T,self.G)), self.G.T).dot(Y)
        # 计算loss
        pre_y = self.G.dot(self.w)
        print(f"loss:{self.culMse(pre_y,Y)}")

    def estimate(self,X,Y):
        """
        测试数据,返回预测准确率
        :param X: 测试数据,200 X 784维
        :param Y: 测试数据的标签,200 X 10维
        """
        hidden_v = np.zeros(self.h_nodes)   # 隐含层结点值
        correct_num = 0
        # 遍历测试样本
        for i in range(X.shape[0]):
            # 计算该测试样本对应的隐藏层结点值
            for j in range(self.h_nodes):
                hidden_v[j] = self.calBasis(X[i],self.centers[j])
            output = hidden_v.dot(self.w)   # 网络输出值ouput
            pre_y = np.argmax(output)   # 预测标签
            y = np.argmax(Y[i])    # 期望标签
            if y == pre_y:
                correct_num = correct_num+1
        return correct_num/X.shape[0]


if __name__ == "__main__":
    # 通过tensorflow读取mnist数据,并对读取到的数据进行处理
    mnist = tf.keras.datasets.mnist
    (train_x,train_y),(test_x,test_y) = mnist.load_data()
    # 将图像数据转为0-1的范围
    train_data = np.zeros((60000, 784))
    train_label = np.zeros((60000, 10))
    test_data = np.zeros((10000, 784))
    test_label = np.zeros((10000, 10))
    for i in range(60000):  # 处理训练数据
        train_data[i] = (np.array(train_x[i]).flatten())/255
        temp = np.zeros(10)
        temp[train_y[i]] = 1
        train_label[i] = temp
    for i in range(10000):  # 处理测试数据
        test_data[i] = (np.array(test_x[i]).flatten())/255
        temp = np.zeros(10)
        temp[test_y[i]] = 1
        test_label[i] = temp

    # RBF网络的输入、隐含、输出层结点个数
    input_nodes = 784
    hidden_nodes = 1000
    output_nodes = 10
    sample_num = 60000

    rbfNet = RBFNet(sample_num,input_nodes,hidden_nodes,output_nodes)
    rbfNet.train(train_data,train_label)

    accuracy = rbfNet.estimate(test_data,test_label)
    print(f"准确率:{accuracy}")

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部