2

だからここでは遅く、私のグーグルスキルは私を失敗させているようです。私は以前に(何度も)SOでいくつかの素晴らしい応答を見つけました、私はあなたたちが助けることができると思いました。

ネイティブObjective-cで実行しようとしているニューラルネットワークがあります。動作しますが、遅すぎます。これらのネットワークは再発しません。私が実行する各ネットワークは約20,000回(128x80回、またはその前後)です。問題は、これらのネットワークが実際には数学関数に要約されることです(各ネットワークは、x、y、dist(x、y)、およびバイアスを入力として受け取り、3つの値を出力する4次元関数です)。

私がやりたいのは、各ネットワークを(1回だけ)関数呼び出し、または実行時にObjective-cのコードブロックに変換することです。

どうすればよいですか?実行する必要のある数学演算の大きな文字列を作成することはできますが、その文字列を実行したり、実行用のコードのブロックに文字列を変換したりするにはどうすればよいですか?

繰り返しになりますが、深夜の検索で失敗したので、これがすでに回答されている場合は申し訳ありません。どんな助けでも大歓迎です。

-ポール

編集:ああ!大成功!ほぼ24時間後、最大4つの入力を持つニューラルネットワークを単一の4次元関数に変換するための作業コードがあります。回答では、DaveDeLongによって提案されたブロック方法を使用しました。

私が将来行ったことをフォローしたい人のために、これが私がしたことの(迅速な)内訳です(これがstackoverflowのエチケットが正しくない場合はすみません):最初に、別のブロックに対していくつかのtypedefを作成しました関数:

typedef CGFloat (^oneDFunction)(CGFloat x);
typedef CGFloat (^twoDFunction)(CGFloat x, CGFloat y);
typedef CGFloat (^threeDFunction)(CGFloat x, CGFloat y, CGFloat z);
typedef CGFloat (^fourDFunction)(CGFloat x, CGFloat y, CGFloat z, CGFloat w);

oneDFunctionはf(x)の形式を取り、twoDはf(x、y)などです。次に、2つのfourDFunctionブロック(および2つのoneD、2つのtwoDなど)を組み合わせる関数を作成しました。

fourDFunction (^combineFourD) (fourDFunction f1, fourDFunction f2) =
  ^(fourDFunction f1,     fourDFunction f2){
    fourDFunction blockToCopy = ^(CGFloat x, CGFloat y, CGFloat z, CGFloat w){
        return f1(x,y,z,w) + f2(x,y,z,w);
    };
    fourDFunction act = [blockToCopy copy];
    [f1 release];
    [f2 release];
    //Need to release act at some point
    return act;            
};

そしてもちろん、すべてのノードのfourD関数に活性化関数を適用する必要があり、各ノードについて、それを接続する重みを掛ける必要があります。

//for applying the activation function
fourDFunction (^applyOneToFourD)( oneDFunction f1, fourDFunction f2) = 
^(oneDFunction f1, fourDFunction f2){
    fourDFunction blockToCopy = ^(CGFloat x, CGFloat y, CGFloat z, CGFloat w){
        return f1(f2(x,y,z,w));
    };    

    fourDFunction act = [blockToCopy copy];
    [f1 release];
    [f2 release];

    //Need to release act at some point
    return act; 

};

//For applying the weight to the function
fourDFunction (^weightCombineFour) (CGFloat x, fourDFunction f1) =
 ^(CGFloat weight, fourDFunction f1)
{
    fourDFunction blockToCopy = ^(CGFloat x, CGFloat y, CGFloat z, CGFloat w){

        return weight*f1(x,y,z,w);
    };

    fourDFunction act = [blockToCopy copy];
    [f1 release];
    //[act release];
    //Need to release act at some point
   return act;

};

次に、ネットワーク内のノードごとに、ソースニューロンからの4つのD関数の合計に接続の重みを掛けたものに活性化関数を適用しました。これらすべてのブロックを作成した後、各出力から最終的な関数を取得しました。したがって、私の出力は入力の個別の4D関数です。

助けてくれてありがとう、これはとてもクールでした。

4

4 に答える 4

4

これはブロックで行うことができます。何かのようなもの:

//specify some parameters
int parameter1 = 42;
int parameter2 = 54;
//create your block
int (^myBlock)(int) = ^(int parameter3){
  return parameter1 * parameter2 * parameter3;
};
//copy the block off the stack
myBlock = [myBlock copy];
//stash the block somewhere so that you can pull it out later
[self saveBlockOffSomewhereElse:myBlock underName:@"myBlock"];
//balance the call to -copy
[myBlock release];

そして他の場所...

int (^retrievedBlock)(int) = [self retrieveBlockWithName:@"myBlock"];
int theAnswer = retrievedBlock(2);  //theAnswer is 4536

評価する数学を表す文字列がある場合は、GCMathParser(高速ですが拡張可能ではありません)または私自身のDDMathParser(低速ですが拡張可能)をチェックできます。

于 2011-03-27T04:52:52.623 に答える
3

あなたの考えはそれほど愚かではありません。実際のところ、LLVMはまさにそのようなこと(コードの生成、コンパイル、リンク、ロード、実行)を行うように設計されており、リンクするライブラリや使用するAPIもあります。

一連のブロックまたはプリミティブ(独自のVMの一種)をつなぎ合わせようとする道をたどることはできますが、速度が遅くなり、おそらくメンテナンスが多くなりますある種のパーサーを作成し、すべてのプリミティブブロックを作成してから、それをすべてつなぎ合わせる必要があります。

コード生成には、おそらくパーサーが必要ですが、コンパイラーでオプティマイザーをクランクアップでき、コードの非常に大きなファイルを1つだけ生成する限り、結果のコードははるかに高速になります、コンパイラのオプティマイザはさらに効果的です。

ただし、プログラムを生成してから、アプリの外部で実行することをお勧めします。これにより、コードを動的にアンロードしようとしている地獄を防ぐことができます。また、生成されたコードがクラッシュしても、アプリケーションが削除されないことも意味します。

LLVM.orgには多くの追加の詳細があります。

(歴史的なメモ-ピクサーのモデリング環境の初期の形式の1つは、文字通り、数十万行の高度にテンプレート化されたC ++コードを出力するTCLベースのシステムでした。)

于 2011-03-27T04:53:18.343 に答える
1

ブロックへの別の投票。プリミティブ操作を表す一連のブロックから始める場合は、それらを複雑な関数を表すより大きなブロックに構成できます。たとえば、いくつかのブロックをパラメーターとして受け取り、各ブロックを順番にコピーして、それを最初のパラメーターとして次のブロックに使用する関数を作成できます。関数の結果は、数学関数を表すブロックになる可能性があります。

おそらく私はここで遅い時間のために狂ったように話しているかもしれませんが、ブロックが他のブロックを参照し、状態を維持する能力は、それらを組み立て操作に非常に適したものにするはずです。

于 2011-03-27T09:30:23.917 に答える
1

別の可能性があります:OpenGLを使用します。

ニューラルネットワークで実行している機能の種類は、GPUで実行されている機能と非常によく似ています。乗算/スケーリング、距離、シグモイドなど...状態をビットマップでエンコードし、ピクセルシェイパーをASCIIとして生成し、提供されたライブラリ呼び出しを使用してコンパイルおよびリンクし、新しい状態で出力「ビットマップ」を生成できます。次に、2つのビットマップを切り替えて、もう一度繰り返します。

ピクセルシェイパーを書くことはあなたが想像するほど難しくはありません。基本的なケースでは、入力ビットマップ/バッファーからピクセルが与えられ、出力バッファーに入れる値を計算します。また、任意のデータベクトルとして機能する可能性のある「テクスチャ」ビットマップを含む、グローバルに設定した任意のパラメータとして、入力バッファと出力バッファの他のすべてのピクセルにアクセスできます。

最新のGPUには複数のパイプラインがあるため、ネイティブCPUマシンコードよりもはるかに優れたパフォーマンスが得られる可能性があります。

于 2011-03-27T05:09:51.823 に答える