[PR]
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
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がわで動くプログラムはこちら:
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...です。
さて今回はあまり自信がありません。
もっとも私はいつも自信がないのですが、今回はいつもよりさらに自信がありません。
プログラムは上手く動くように見えるのですが、その理論的背景がよくわかりません!
間違いがあったら訂正していただけるとありがたいです。
[追記] どうもこちらのほうが正しいような気がしてきました。リンク先もご覧ください。どちらの性能が高いかというとこのページのやり方のほうがいい気がします。うーんどっちを使うべきなんでしょう?
[追記2] こちらもご覧ください。この記事のプログラムは、学習データに1が多いと上手く学習できないようです。それを修正しました。
今回のテーマは制限(制約)付きボルツマンマシンの実装、実数バージョンです。
この前の実装は、バイナリでした。
つまり、可視ニューロンには発火しているかどうかの2通りしかありませんでした。
発火状態は0か1かしか扱えなかったのです。
(その割には可視ニューロンの発火状態の型が(boolではなく)doubleだったりと妙なことになっていましたが)