web-dev-qa-db-ja.com

シンプルな多層ニューラルネットワークの実装

しばらく前、私は機械学習を使って冒険を始めました(過去2年間の研究期間中)。私は多くの本を読み、ニューラルネットワークを除く機械学習アルゴリズムを使用して多くのコードを記述しましたが、これらは私の範囲外でした。私はこのトピックに非常に興味がありますが、大きな問題があります。私が読んだ本にはすべて2つの主要な問題があります。

  1. 数学方程式のトーンが含まれています。講義の後、私はそれらに非常に精通しており、紙で計算を行うことができます。
  2. いくつかの複雑なコンテキスト(たとえば、インターネットショップの販売率の調査)に埋め込まれた大きな例を含み、ニューラルネットワークの実装を理解するには、コンテキストを再現するために多くのコードを記述する必要があります。不足しているもの-多くのコンテキストと方程式のない単純な簡単な実装。

多層知覚(ニューラルネットワーク)の簡単な実装を見つけられる場所を教えてください。理論的な知識は必要ありません。また、コンテキストに埋め込まれた例も必要ありません。時間と労力を節約するために、いくつかのスクリプト言語を好みます-以前の作業の99%はPythonで行われました。

これは私が以前読んだ本のリストです(私が欲しいものが見つかりませんでした):

  1. 機械学習の実際
  2. 集合知能のプログラミング
  3. 機械学習:アルゴリズムの視点
  4. Javaのニューラルネットワークの概要
  5. C#のニューラルネットワークの概要
27
Animattronic

簡単な実装

以下は、Pythonのクラスを使用した読み取り可能な実装です。この実装は、効率性と理解しやすさのトレードオフです。

    import math
    import random

    BIAS = -1

    """
    To view the structure of the Neural Network, type
    print network_name
    """

    class Neuron:
        def __init__(self, n_inputs ):
            self.n_inputs = n_inputs
            self.set_weights( [random.uniform(0,1) for x in range(0,n_inputs+1)] ) # +1 for bias weight

        def sum(self, inputs ):
            # Does not include the bias
            return sum(val*self.weights[i] for i,val in enumerate(inputs))

        def set_weights(self, weights ):
            self.weights = weights

        def __str__(self):
            return 'Weights: %s, Bias: %s' % ( str(self.weights[:-1]),str(self.weights[-1]) )

    class NeuronLayer:
        def __init__(self, n_neurons, n_inputs):
            self.n_neurons = n_neurons
            self.neurons = [Neuron( n_inputs ) for _ in range(0,self.n_neurons)]

        def __str__(self):
            return 'Layer:\n\t'+'\n\t'.join([str(neuron) for neuron in self.neurons])+''

    class NeuralNetwork:
        def __init__(self, n_inputs, n_outputs, n_neurons_to_hl, n_hidden_layers):
            self.n_inputs = n_inputs
            self.n_outputs = n_outputs
            self.n_hidden_layers = n_hidden_layers
            self.n_neurons_to_hl = n_neurons_to_hl

            # Do not touch
            self._create_network()
            self._n_weights = None
            # end

        def _create_network(self):
            if self.n_hidden_layers>0:
                # create the first layer
                self.layers = [NeuronLayer( self.n_neurons_to_hl,self.n_inputs )]

                # create hidden layers
                self.layers += [NeuronLayer( self.n_neurons_to_hl,self.n_neurons_to_hl ) for _ in range(0,self.n_hidden_layers)]

                # hidden-to-output layer
                self.layers += [NeuronLayer( self.n_outputs,self.n_neurons_to_hl )]
            else:
                # If we don't require hidden layers
                self.layers = [NeuronLayer( self.n_outputs,self.n_inputs )]

        def get_weights(self):
            weights = []

            for layer in self.layers:
                for neuron in layer.neurons:
                    weights += neuron.weights

            return weights

        @property
        def n_weights(self):
            if not self._n_weights:
                self._n_weights = 0
                for layer in self.layers:
                    for neuron in layer.neurons:
                        self._n_weights += neuron.n_inputs+1 # +1 for bias weight
            return self._n_weights

        def set_weights(self, weights ):
            assert len(weights)==self.n_weights, "Incorrect amount of weights."

            stop = 0
            for layer in self.layers:
                for neuron in layer.neurons:
                    start, stop = stop, stop+(neuron.n_inputs+1)
                    neuron.set_weights( weights[start:stop] )
            return self

        def update(self, inputs ):
            assert len(inputs)==self.n_inputs, "Incorrect amount of inputs."

            for layer in self.layers:
                outputs = []
                for neuron in layer.neurons:
                    tot = neuron.sum(inputs) + neuron.weights[-1]*BIAS
                    outputs.append( self.sigmoid(tot) )
                inputs = outputs   
            return outputs

        def sigmoid(self, activation,response=1 ):
            # the activation function
            try:
                return 1/(1+math.e**(-activation/response))
            except OverflowError:
                return float("inf")

        def __str__(self):
            return '\n'.join([str(i+1)+' '+str(layer) for i,layer in enumerate(self.layers)])

より効率的な実装(学習あり)

学習(バックプロパゲーション)を備えたニューラルネットワークのより効率的な例を探している場合は、私の こちらのニューラルネットワークGithubリポジトリ をご覧ください。

32
jorgenkg

うーん、これはトリッキーです。以前にも同じ問題を抱えていましたが、優れたものの重く負荷のかかった説明と、すぐに使用できる実装の間には何も見つかりませんでした。

PyBrainのようなready実装の問題は、詳細を隠すため、ANNの実装方法の学習に興味がある人は他の何かを必要としていることです。そのようなソリューションのコードを読むことは、パフォーマンスを改善するためにヒューリスティックを使用することが多く、初心者にとってコードを追跡するのが難しくなるため、挑戦することもできます。

ただし、使用できるリソースはいくつかあります。

http://msdn.Microsoft.com/en-us/magazine/jj658979.aspx

http://itee.uq.edu.au/~cogs2010/cmc/chapters/BackProp/

http://www.codeproject.com/Articles/19323/Image-Recognition-with-Neural-Networks

http://freedelta.free.fr/r/php-code-samples/artificial-intelligence-neural-network-backpropagation/

7
Pedrom

Numpyを使用してフィードフォワードニューラルネットワークを実装する方法の例を次に示します。最初にnumpyをインポートし、入力とターゲットの次元を指定します。

import numpy as np

input_dim = 1000
target_dim = 10

ここでネットワーク構造を構築します。 Bishopの優れた「パターン認識と機械学習」で示唆されているように、numpy行列の最後の行をバイアスの重みと見なし、アクティベーションの最後の列をバイアスニューロンと見なすことができます。最初/最後の重み行列の入力/出力次元は、1より大きい必要があります。

dimensions = [input_dim+1, 500, 500, target_dim+1]

weight_matrices = []
for i in range(len(dimensions)-1):
  weight_matrix = np.ones((dimensions[i], dimensions[i]))
  weight_matrices.append(weight_matrix)

入力が2d numpy行列に格納され、各行が1つのサンプルに対応し、列がサンプルの属性に対応する場合、次のようにネットワークを介して伝播できます(アクティベーション関数としてロジスティックシグモイド関数を想定)

def activate_network(inputs):
  activations = [] # we store the activations for each layer here
  a = np.ones((inputs.shape[0], inputs.shape[1]+1)) #add the bias to the inputs
  a[:,:-1] = inputs

  for w in weight_matrices:
    x = a.dot(w) # sum of weighted inputs
    a = 1. / (1. - np.exp(-x)) # apply logistic sigmoid activation
    a[:,-1] = 1. # bias for the next layer.
    activations.append(a)

  return activations

activationsの最後の要素はネットワークの出力になりますが、注意してください、バイアスの追加列を省略する必要があるため、出力はactivations[-1][:,:-1]

ネットワークをトレーニングするには、数行のコードを追加するバックプロパゲーションを実装する必要があります。基本的に、activationsの最後の要素から最初の要素にループする必要があります。各逆伝播ステップの前に、各層のエラー信号のバイアス列を必ずゼロに設定してください。

6
schreon

ここ はネイティブPythonのbackpropアルゴリズムです。

5
david_adler

PyBrain を試しましたか? 文書化された のようです。

0
Salem