人工知性を作りたい

私が日々、挑戦したことや学んだことなどを紹介していく雑記ブログです。 (新しいAI技術HTM, 専門の音声信号処理, 趣味のアニメ等も書いてます。)

AndroidでHTM.core(AIライブラリ)を使えるようにしてみた【 #htm #Androidアプリ 】

 

f:id:hiro-htm877:20200113233157p:plain





 

f:id:hiro-htm877:20190601202549p:plain

 

 

 

  

 

 

 

従来のディープラーニングと比べ処理量が少ないHTMをAndroidのアプリとして実装したいと思い取り組みました。

Androidは、まだまだ初心者なこともあり使えるようにするだけで2ヶ月半もかかりました!(笑)

また、htm.coreの全ての機能を使えるようになったのではなく大きくは、RandomDestributedEncoder, SpatialPooler, TemporalMemolyを使えるようにし以上度などは出せるようになりました。

 

本記事のテーマ

AndroidでHTM.coreを使えるようにする」

・RandomDestributedEncoder, SpatialPooler, TemporalMemolyの実装

(Classifierなどは未実装)

・TMを使用した簡単なデモの実行例

実装方法についてはまたの機会として、今回はTMデモの実行結果だけを紹介したいと思います。

 

使用したPC:Ubuntu18.04

 

cppライブラリのAndroidアプリ実装方法(簡略)

Android Studioでアプリ作成

1.JNIを使ったNative実装

2.Cmake、Gradleを使ったAndroidアプリのビルド

 

Temporal Memoryデモアプリの実装

デモアプリの内容

1.A→B→C→D→Eの順番を学習させる

2.A→B→C→D→Eの異常度を計算する。

 

アプリのシーケンス

Encode→TM→Anomaly出力

 

Encode

SDR=SparseDistributedRepresentation(粗分散表現)

SDRのサイズ:50

A:[ 0〜 9]=1

B:[10〜19]=1

C:[20〜29]=1

D:[30〜39]=1

E:[40〜49]=1

 例:

A=[1 1 1 1 1 1 1 1 1 1

       0 0 0 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0 0 0 ]

 

Temporal Memory〜Anomaly計算

1.A→B→C→D→Eの順番で学習させる

2.学習FalseでA→B→C→D→Eの順で異常度を計算する。

例:Aの学習

    tm_test.compute(sdr_A, true);
tm_test.activateDendrites(); //required to enable tm.getPredictiveCells()
outTM = tm_test.cellsToColumns( tm_test.getPredictiveCells() );

an_test = tm_test.anomaly;

 

 

Androidアプリ側の実装

onCreateで一回だけ実行する。

onResumeなどで実行すると、Androidのライフサイクルという仕組みから何回も実行されてしまう。

public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
     Compute();
}

public native double
Compute();
}

 

Native側(Cpp)の実装

とりあえず、入力するSDRの準備〜AをTMで学習させるまでの実装コードを載せます。

Native側でLogを出すには__android_log_printを使用する。

__android_log_print(ANDROID_LOG_DEBUG,"uchida","num %d : vec_A %d",num, x);

const int vec_size = 50;

//入力するSDRの準備
vector<int> A (vec_size, 0);
vector<int> B (vec_size, 0);
vector<int> C (vec_size, 0);
vector<int> D (vec_size, 0);
vector<int> E (vec_size, 0);

for(int i; i<10; i++){
A[i] = 1;
B[i+10] = 1;
C[i+20] = 1;
D[i+30] = 1;
E[i+40] = 1;
__android_log_print(ANDROID_LOG_DEBUG,"uchida","i %d",i);
}

int num = 0;
for(auto x: A){
__android_log_print(ANDROID_LOG_DEBUG,"uchida","num %d : vec_A %d",num, x);
num += 1;
}
// TMの設定
TemporalMemory tm_test(vector<UInt>{vec_size}, 1);
tm_test.setInitialPermanence(0.5);
tm_test.setMinThreshold(8);
tm_test.setMaxNewSynapseCount(20);
tm_test.setPermanenceIncrement(0.1);
tm_test.setPermanenceDecrement(0.0);
tm_test.setActivationThreshold(8);

SDR sdr_A({50});
sdr_A.setDense(A);
SDR sdr_B({50});
sdr_B.setDense(B);
SDR sdr_C({50});
sdr_C.setDense(C);
SDR sdr_D({50});
sdr_D.setDense(D);
SDR sdr_E({50});
sdr_E.setDense(E);

num = 0;
for(auto x: sdr_A.getDense()){
__android_log_print(ANDROID_LOG_DEBUG,"uchida","num %d : sdr_A %d",num, x);
num += 1;
}
__android_log_print(ANDROID_LOG_DEBUG,"uchida","Send this simple sequence to the temporal memory for learning.");

SDR activeColumns({50});
Timer timeTM, timeAnLikelihood;
Real an_test = 0.0f, anLikely_test = 0.0f; //for anomaly:
AnomalyLikelihood anLikelihood_test;
MovingAverage avgAnom10_test(1);
Real avgAnomOld_test = 1.0;
SDR outTM({50});

timeTM.start();
tm_test.compute(sdr_A, true);
tm_test.activateDendrites(); //required to enable tm.getPredictiveCells()
outTM = tm_test.cellsToColumns( tm_test.getPredictiveCells() );

an_test = tm_test.anomaly;

 


【実行結果】
・学習中
D/uchida: anomaly A : 1.000000
D/uchida: anomaly B : 1.000000
D/uchida: anomaly C : 1.000000
D/uchida: anomaly D : 1.000000
D/uchida: anomaly E : 1.000000
・学習OFF、異常予測
D/uchida: anomaly A : 1.000000
D/uchida: anomaly B : 0.000000
D/uchida: anomaly C : 0.000000
D/uchida: anomaly D : 0.000000
D/uchida: anomaly E : 0.000000


学習OFFの最初は一つ前のデータがないため以上が1を示しているが、その後は学習させた順番で入力しているため異常が0となっている。
簡易的なテストであるがとりあえずAndroidでhtm.coreがちゃんと動いている様子です。

次は、Sine波の予測を行ってもう少しビジュアル的にもアプリらしいものを作成して見たいと思います。

以上です。


実験2 A→C→D→B→Eの順

ちなみに、A→C→D→B→Eの順番でも実験してみましたので結果だけ記載します。

 C→Dの順のみ学習しているので異常度は”0”それ以外は知らない入力順なので異常と判断しています。

2020-01-13 23:27:58.176 31234-31234/? D/uchida: anomaly A : 1.000000
2020-01-13 23:27:58.176 31234-31234/? D/uchida: anomaly C : 1.000000
2020-01-13 23:27:58.176 31234-31234/? D/uchida: anomaly D : 0.000000
2020-01-13 23:27:58.176 31234-31234/? D/uchida: anomaly B : 1.000000
2020-01-13 23:27:58.177 31234-31234/? D/uchida: anomaly E : 1.000000