[DeepLearning] Caffeでsin関数近似に挑戦してみた（失敗）

DeepLearningの勉強を開始。
自環境がWindowsなのでとりあえずCaffeをインストール。
MNISTサンプルも無事動作したので環境はOK。
ということで、sin関数近似をやらせてみた。

# 非線形関数近似
Chainerではちらほらやっている人が居るsin関数を近似してみる。

```cpp:sinApproximation.cpp
#include <iostream>
#include <array>
#include <memory> 
#include <cassert>
#include <random> 
#include <caffe/caffe.hpp> 
#include <stdio.h>
#include <stdlib.h>

using namespace std;
using namespace caffe;

#define SOLVER_PATH "solver.prototxt"
#define DEMENSION 1
#define BATCH_SIZE 256
#define COUNT 10
#define PI 3.141592

int main(int argc, char** argv) { 
	int DataSize = BATCH_SIZE * COUNT; 
	std::array<float, BATCH_SIZE * COUNT * DEMENSION> input_data; 
	std::array<float,BATCH_SIZE * COUNT* DEMENSION> target_data; 

	float x = 0;
	
	for (auto i = 0; i < DataSize; ++i) {
		float target = sin(x);
		input_data[i] = x;
				
		target_data[i] = target;
		x += 0.5;
	} 

	// 回帰でラベルは使用しないため、ダミーデータ用意
	std::array<float, BATCH_SIZE * COUNT> dummy_data; 
	std::fill(dummy_data.begin(), dummy_data.end(), 0.0); 

	// GPUモードで実行
	Caffe::set_mode(Caffe::GPU);

	// Solver 設定 
	caffe::SolverParameter solver_param; 
	caffe::ReadProtoFromTextFileOrDie(SOLVER_PATH, &solver_param); 
	SGDSolver<float> solver(solver_param);
	const auto net = solver.net(); 

	// 入力 : "input" 
	const auto input_layer = 
		boost::dynamic_pointer_cast<caffe::MemoryDataLayer<float>>(net->layer_by_name("input")); 
	input_layer->Reset(input_data.data(), dummy_data.data(), kDataSize);

	// 目標 : "target" 
	const auto target_layer = 
		boost::dynamic_pointer_cast<caffe::MemoryDataLayer<float>>(net->layer_by_name("target")); 
	target_layer->Reset(target_data.data(), dummy_data.data(), kDataSize); 

	// 学習実行 
	solver.Solve(); 

	// 学習された（ハズの）モデルを使って推測
	input_layer->Reset(input_data.data(), dummy_data.data(), kDataSize); 
	net->ForwardPrefilled(nullptr);
	
	FILE *outputfile; 
	outputfile = fopen("output.txt", "w"); 

	for (auto i = 0; i < BATCH_SIZE; ++i) { 
		// 各層のデータをファイル出力
		fprintf(outputfile, "%f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f\t %f \n",
			net->blob_by_name("ip1")->cpu_data()[i],
			net->blob_by_name("ip1")->data_at(i,1,1,1),
			net->blob_by_name("relu1")->cpu_data()[i],
			net->blob_by_name("ip2")->cpu_data()[i],
			net->blob_by_name("ip2")->data_at(i,1,1,1),
			net->blob_by_name("relu2")->cpu_data()[i],
			net->blob_by_name("ip3")->cpu_data()[i],
			net->blob_by_name("ip3")->data_at(i,1,1,1),
			net->blob_by_name("loss")->cpu_data()[i],
			net->blob_by_name("loss")->data_at(i,1,1,1),
			net->blob_by_name("target")->cpu_data()[i],
			input_data[i],
			target_data[i]);
	} 
	fclose(outputfile); 
}
```
設定系はこんな具合で。

```protobuf:solver.prototxt
train_net:"layers.prototxt"
base_lr:0.0001
momentum:0.9
lr_policy:"inv
gamma:0.01
stepsize:1
max_iter:256
display:10
solver_mode: GPU
```

```protobuf:layers.prototxt
name:"STUDY"
layers{
	name:"input"
	type:MEMORY_DATA
	top:"ip1"
	top:"dummy_label1"
	memory_data_param{
		batch_size:256
		channels:1
		height:1
		width:1
	}
}
layers{
	name:"ip1"
	type:INNER_PRODUCT
	bottom:"ip1"
	top:"relu1"
	inner_product_param{
		num_output:256
		weight_filler{
    	  type: "xavier"
		}
		bias_filler{
    	  type: "constant"
    	  value:0
		}
	}
}
layers{
	name:"relu1"
	type:RELU
	bottom:"relu1"
	top:"ip2"
}
layers{
	name:"ip2"
	type:INNER_PRODUCT
	bottom:"ip2"
	top:"relu2"
	inner_product_param{
		num_output:256
		weight_filler{
    	  type: "xavier"
		}
		bias_filler{
    	  type: "constant"
    	  value:0
		}
	}
}
layers{
	name:"relu2"
	type:RELU
	bottom:"relu2"
	top:"ip3"
}
layers{
	name:"ip3"
	type:INNER_PRODUCT
	bottom:"ip3"
	top:"loss"
	inner_product_param{
		num_output:1
		weight_filler{
    	  type: "xavier"
		}
		bias_filler{
    	  type: "constant"
    	  value:0
		}
	}
}
layers{
	name:"target"
	type:MEMORY_DATA
	top:"target"
	top:"dummy_label2"
	memory_data_param{
		batch_size:256
		channels:1
		height:1
		width:1
	}
}
layers{
	name:"loss"
	type:EUCLIDEAN_LOSS
	bottom:"target"
	bottom:"loss"
}

```
活性化にはSIGMOIDかReLUで迷ったけどとりあえずReLUを採用してみることに。

内積→ReLU→内積→ReLU→内積←ここの値が欲しい

ReLU使うときは内積層のユニット数多めにすればなんでも近似できるよ
ってどこかできいたので、とりあえず256個。

いざ実行。
・・・・・



カスリもしない。
というか結果の取り方これで合ってる・・・のか？

Caffeは画像分類系ばかりで回帰方面の情報がWeb上に少ない気がする。。

知見のある方、なにとぞアドバイスをお願いします・・・