径向基(RBF)神经网络python实现

from numpy import array, append, vstack, transpose, reshape, \
                  dot, true_divide, mean, exp, sqrt, log, \
                  loadtxt, savetxt, zeros, frombuffer
from numpy.linalg import norm, lstsq
from multiprocessing import Process, Array
from random import sample
from time import time
from sys import stdout
from ctypes import c_double
from h5py import File


def metrics(a, b):
    return norm(a - b)


def gaussian (x, mu, sigma):
    return exp(- metrics(mu, x)**2 / (2 * sigma**2))


def multiQuadric (x, mu, sigma):
    return pow(metrics(mu,x)**2 + sigma**2, 0.5)


def invMultiQuadric (x, mu, sigma):
    return pow(metrics(mu,x)**2 + sigma**2, -0.5)


def plateSpine (x,mu):
    r = metrics(mu,x)
    return (r**2) * log(r)


class Rbf:
    def __init__(self, prefix = 'rbf', workers = 4, extra_neurons = 0, from_files = None):
        self.prefix = prefix
        self.workers = workers
        self.extra_neurons = extra_neurons

        # Import partial model
        if from_files is not None:            
            w_handle = self.w_handle = File(from_files['w'], 'r')
            mu_handle = self.mu_handle = File(from_files['mu'], 'r')
            sigma_handle = self.sigma_handle = File(from_files['sigma'], 'r')
            
            self.w = w_handle['w']
            self.mu = mu_handle['mu']
            self.sigmas = sigma_handle['sigmas']
            
            self.neurons = self.sigmas.shape[0]

    def _calculate_error(self, y):
        self.error = mean(abs(self.os - y))
        self.relative_error = true_divide(self.error, mean(y))

    def _generate_mu(self, x):
        n = self.n
        extra_neurons = self.extra_neurons

        # TODO: Make reusable
        mu_clusters = loadtxt('clusters100.txt', delimiter='\t')

        mu_indices = sample(range(n), extra_neurons)
        mu_new = x[mu_indices, :]
        mu = vstack((mu_clusters, mu_new))

        return mu

    def _calculate_sigmas(self):
        neurons = self.neurons
        mu = self.mu

        sigmas = zeros((neurons, ))
        for i in xrange(neurons):
            dists = [0 for _ in xrange(neurons)]
            for j in xrange(neurons):
                if i != j:
                    dists[j] = metrics(mu[i], mu[j])
            sigmas[i] = mean(dists)* 2
                      # max(dists) / sqrt(neurons * 2))
        return sigmas

    def _calculate_phi(self, x):
        C = self.workers
        neurons = self.neurons
        mu = self.mu
        sigmas = self.sigmas
        phi = self.phi = None
        n = self.n


        def heavy_lifting(c, phi):
            s = jobs[c][1] - jobs[c][0]
            for k, i in enumerate(xrange(jobs[c][0], jobs[c][1])):
                for j in xrange(neurons):
                    # phi[i, j] = metrics(x[i,:], mu[j])**3)
                    # phi[i, j] = plateSpine(x[i,:], mu[j]))
                    # phi[i, j] = invMultiQuadric(x[i,:], mu[j], sigmas[j]))
                    phi[i, j] = multiQuadric(x[i,:], mu[j], sigmas[j])
                    # phi[i, j] = gaussian(x[i,:], mu[j], sigmas[j]))
                if k % 1000 == 0:
                    percent = true_divide(k, s)*100
                    print(c, ': {:2.2f}%'.format(percent))
            print(c, ': Done')
        
        # distributing the work between 4 workers
        shared_array = Array(c_double, n * neurons)
        phi = frombuffer(shared_array.get_obj())
        phi = phi.reshape((n, neurons))

        jobs = []
        workers = []

        p = n / C
        m = n % C
        for c in range(C):
            jobs.append((c*p, (c+1)*p + (m if c == C-1 else 0)))
            worker = Process(target = heavy_lifting, args = (c, phi))
            workers.append(worker)
            worker.start()

        for worker in workers:
            worker.join()

        return phi

    def _do_algebra(self, y):
        phi = self.phi

        w = lstsq(phi, y)[0]
        os = dot(w, transpose(phi))
        return w, os
        # Saving to HDF5
        os_h5 = os_handle.create_dataset('os', data = os)

    def train(self, x, y):
        self.n = x.shape[0]

        ## Initialize HDF5 caches
        prefix = self.prefix
        postfix = str(self.n) + '-' + str(self.extra_neurons) + '.hdf5'
        name_template = prefix + '-{}-' + postfix
        phi_handle = self.phi_handle = File(name_template.format('phi'), 'w')
        os_handle = self.w_handle = File(name_template.format('os'), 'w')
        w_handle = self.w_handle = File(name_template.format('w'), 'w')
        mu_handle = self.mu_handle = File(name_template.format('mu'), 'w')
        sigma_handle = self.sigma_handle = File(name_template.format('sigma'), 'w')

        ## Mu generation
        mu = self.mu = self._generate_mu(x)
        self.neurons = mu.shape[0]
        print('({} neurons)'.format(self.neurons))
        # Save to HDF5
        mu_h5 = mu_handle.create_dataset('mu', data = mu)

        ## Sigma calculation
        print('Calculating Sigma...')
        sigmas = self.sigmas = self._calculate_sigmas()
        # Save to HDF5
        sigmas_h5 = sigma_handle.create_dataset('sigmas', data = sigmas)
        print('Done')

        ## Phi calculation
        print('Calculating Phi...')
        phi = self.phi = self._calculate_phi(x)
        print('Done')
        # Saving to HDF5
        print('Serializing...')
        phi_h5 = phi_handle.create_dataset('phi', data = phi)
        del phi
        self.phi = phi_h5
        print('Done')

        ## Algebra
        print('Doing final algebra...')
        w, os = self.w, _ = self._do_algebra(y)
        # Saving to HDF5
        w_h5 = w_handle.create_dataset('w', data = w)
        os_h5 = os_handle.create_dataset('os', data = os)

        ## Calculate error
        self._calculate_error(y)
        print('Done')

    def predict(self, test_data):
        mu = self.mu = self.mu.value
        sigmas = self.sigmas = self.sigmas.value
        w = self.w = self.w.value

        print('Calculating phi for test data...')
        phi = self._calculate_phi(test_data)
        os = dot(w, transpose(phi))
        savetxt('iok3834.txt', os, delimiter='\n')
        return os

    @property
    def summary(self):
        return '\n'.join( \
            ['-----------------',
            'Training set size: {}'.format(self.n),
            'Hidden layer size: {}'.format(self.neurons),
            '-----------------',
            'Absolute error   : {:02.2f}'.format(self.error),
            'Relative error   : {:02.2f}%'.format(self.relative_error * 100)])


def predict(test_data):
    mu = File('rbf-mu-212243-2400.hdf5', 'r')['mu'].value
    sigmas = File('rbf-sigma-212243-2400.hdf5', 'r')['sigmas'].value
    w = File('rbf-w-212243-2400.hdf5', 'r')['w'].value

    n = test_data.shape[0]  
    neur = mu.shape[0]  
    
    mu = transpose(mu)
    mu.reshape((n, neur))   

    phi = zeros((n, neur))
    for i in range(n):
        for j in range(neur):
            phi[i, j] = multiQuadric(test_data[i,:], mu[j], sigmas[j])

    os = dot(w, transpose(phi))
    savetxt('iok3834.txt', os, delimiter='\n')
    return os

Python 中的径向函数 (Radial Basis Function, RBF) 神经网络是一种径向函数作为激活函数的神经网络模型。这种类型的网络主要用于解决函数逼近和分类问题,特别适合处理高维数据。 RBF 神经网络的工作原理: 1. **输入映射**:每个输入特征被映射到一个高维空间,通常是通过核函数(如径向函数)实现。 2. **中心点和权重**:网络包含多个中心点或节点,每个节点对应一个高维空间中的点。节点的权重决定了该点对输出的影响。 3. **激活函数**:RBF 神经元使用径向函数作为激活函数,其值取决于输入样本与中心点之间的距离。 4. **解码过程**:网络通过加权和这些RBF函数的输出,以及一个偏置项,计算出最终的输出结果。 **Python 实现**: - 在 scikit-learn 库中有一个 RBF 复制器模型 (`sklearn.neural_network.MLPRegressor` 或 `sklearn.neural_network.MLPClassifier` 的 `activation` 参数可以设置为 `'rbf'`,用于创建 RBF 神经网络。 - 如果想要更底层的控制,可以使用其他深度学习库如 Keras 或 PyTorch,它们也提供了构建 RBF 神经网络的功能,通过自定义层或者使用预定义的函数。 **相关问题--:** 1. 如何在 scikit-learn 中创建 RBF 神经网络? 2. RBF 神经网络相比于其他类型的神经网络有何优势? 3. 使用 RBF 神经网络时如何选择合适的中心点和高斯函数参数?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值