忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


GPUでニューラルネットワーク更新 (OpenCL)

ニューロン更新

Deep Learningに備えて色々やってみます。
Deep Learningは重いことがわかったので、GPUで計算をしましょう。

using Cloo;
using System.Linq;

class Program
{
    static void Main()
    {
        ComputePlatform platform = ComputePlatform.Platforms[0];
        ComputeDevice[] devices = platform
            .Devices
            .Where(d => d.Type == ComputeDeviceTypes.Gpu)
            .ToArray();
        ComputeContext context = new ComputeContext(
            devices,
            new ComputeContextPropertyList(platform),
            null,
            System.IntPtr.Zero
            );
        ComputeCommandQueue commandQueue = new ComputeCommandQueue(
            context,
            devices[0],
            ComputeCommandQueueFlags.None
            );
        ComputeProgram program = new ComputeProgram(
            context,
            System.IO.File.ReadAllText("myKernelProgram.cl")
            );
        try
        {
            program.Build(devices, null, null, System.IntPtr.Zero);
        }
        catch
        {
            System.Console.WriteLine(program.GetBuildLog(devices[0]));
        }

        ComputeKernel kernel = program.CreateKernel("updateVisibleNeurons");

        int visibleNeuronCount = 3;
        int hiddenNeuronCount = 2;
        ComputeBuffer<float> visibleNeuronValues = new ComputeBuffer<float>(
            context,
            ComputeMemoryFlags.ReadWrite,
            visibleNeuronCount
            );
        ComputeBuffer<float> visibleNeuronBiases = new ComputeBuffer<float>(
            context,
            ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer,
            new float[visibleNeuronCount]
            );
        ComputeBuffer<float> weights = new ComputeBuffer<float>(
            context,
            ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer,
            Enumerable.Range(0, visibleNeuronCount * hiddenNeuronCount).Select(i => (float)i).ToArray()
            );
        ComputeBuffer<float> hiddenNeuronValues = new ComputeBuffer<float>(
            context,
            ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer,
            Enumerable.Range(0, hiddenNeuronCount).Select(i => (float)i).ToArray()
            );
        kernel.SetMemoryArgument(0, visibleNeuronValues);
        kernel.SetMemoryArgument(1, visibleNeuronBiases);
        kernel.SetMemoryArgument(2, weights);
        kernel.SetMemoryArgument(3, hiddenNeuronValues);
        kernel.SetValueArgument(4, visibleNeuronCount);
        kernel.SetValueArgument(5, hiddenNeuronCount);


        commandQueue.Execute(
            kernel,
            null,
            new long[] { visibleNeuronCount },
            new long[] { 1 },
            null
            );
        float[] resultVisibleNeuronValues = new float[visibleNeuronCount];
        commandQueue.ReadFromBuffer(visibleNeuronValues, ref resultVisibleNeuronValues, true, null);

        foreach (var number in resultVisibleNeuronValues)
        {
            System.Console.WriteLine(number);
        }

        hiddenNeuronValues.Dispose();
        weights.Dispose();
        visibleNeuronBiases.Dispose();
        visibleNeuronValues.Dispose();

        kernel.Dispose();
        commandQueue.Dispose();
        program.Dispose();
        context.Dispose();
    }
}

GPUがわで動くプログラムはこちら:

myKernelProgram.cl

float sigmoid(float x)
{
	return 1.0f / (1.0f + exp(-x));
}

__kernel void updateVisibleNeurons(
	__global float *resultVisibleNeuronValues,
	__global float *visibleNeuronBiases, 
	__global float *weights, 
	__global float *hiddenNeuronValues,
	int visibleNeuronCount,
	int hiddenNeuronCount)
{
	int visibleNeuronIndex = get_global_id(0);
	float sum = 0;

	for(int i = 0; i < hiddenNeuronCount;i++)
	{
		sum += weights[visibleNeuronIndex * hiddenNeuronCount + i] * hiddenNeuronValues[i];
	}

	resultVisibleNeuronValues[visibleNeuronIndex] 
		= sigmoid(sum + visibleNeuronBiases[visibleNeuronIndex]);
}

このプログラムを実行すると、次のようになります:

0.7310586
0.9525741
0.9933071

上手く動いているようですね。
※sigmoid(1)は0.73...です。

拍手[1回]

PR

かんたん!制限付きボルツマンマシン実装 実数(0から1)バージョン (C#) [Deep Learningシリーズ]

ニューロンの発火状態が実数

さて今回はあまり自信がありません。
もっとも私はいつも自信がないのですが、今回はいつもよりさらに自信がありません。
プログラムは上手く動くように見えるのですが、その理論的背景がよくわかりません!
間違いがあったら訂正していただけるとありがたいです。


[追記] どうもこちらのほうが正しいような気がしてきました。リンク先もご覧ください。どちらの性能が高いかというとこのページのやり方のほうがいい気がします。うーんどっちを使うべきなんでしょう?

[追記2] こちらもご覧ください。この記事のプログラムは、学習データに1が多いと上手く学習できないようです。それを修正しました。

今回のテーマは制限(制約)付きボルツマンマシンの実装、実数バージョンです。
この前の実装は、バイナリでした。
つまり、可視ニューロンには発火しているかどうかの2通りしかありませんでした。
発火状態は0か1かしか扱えなかったのです。
(その割には可視ニューロンの発火状態の型が(boolではなく)doubleだったりと妙なことになっていましたが)



バイナリなペンギン
2通りしか無いと画像はこうなります。)



拍手[1回]


かんたん!制限付きボルツマンマシン コントラスティブ・ダイバージェンス(Contrastive Divergence)法[Deep Learningシリーズ]

コントラスティブ・ダイバージェンス法

制限付きボルツマンマシン(Restricted Boltzmann Machine : RBM)は覚えたパターンを後で思い出す能力を持ったニューラルネットワークです。
あるパターンを覚え、後でそれに似たパターンを入力してやると、最初に教えたパターンを思い出すことができます。
制限付きボルツマンマシンはDeep Learningするネットワークの一部に使われています。
ですからDeep Learningしようと思ったら、制限付きボルツマンマシンを学んで損はないでしょう。



制限付きボルツマンマシンの学習には、コントラスティブ・ダイバージェンス(Contrastive Divergence : CD)という方法が有名なようです。
ですので、今回はこのコントラスティブ・ダイバージェンス法について解説します。

拍手[15回]


かんたん!制限付きボルツマンマシン実装 (C#) バイナリ(0と1)バージョン [Deep Learningシリーズ]

Implementing Restricted Boltzmann Machine(RBM) in C#

YUSUKE SUGOMORIさんのjavaコードやその他のコードいろいろを参考にしてC#で制限付きボルツマンマシンを実装してみました。
私好みに書き換えていくとだいぶプログラムの行数が無駄に膨れ上がってしまいましたが、まあよしとしましょう。


拍手[3回]


[Deep Learningシリーズ] かんたんHopfieldネットワーク

Deep Learning

最近Deep Learningというものが話題になっています。
Deep Learningはコンピュータの学習手法の一つです。
一年ほど前(2012年)GoogleがコンピュータにたくさんのYoutube画像を見せネコの顔を自発的に学ばせたということで有名ですね。
人工知能学会誌には現在ディープラーニングの解説が連載中です。
Deep Learningはコンピュータ関係で現在最もホットな話題の一つといえるでしょう。

というわけでこのブログでもDeep Learningを取り上げてみたいと思います。
しかしいきなりDeep Learningの全容に迫るのは難しいのでまずは簡単な話から始めましょう。
今回はHopfield(ホップフィールド)ネットワークです。

拍手[10回]