2018年4月15日日曜日

tiny-dnn で遊ぼ (AutoEncoder)

#include "tiny_dnn/tiny_dnn.h"

namespace td = tiny_dnn;

#include "AudioFile.h"

#include <vector>
#include <random>

//Some traning variable 
const int SAMPLE_NUM = 1024;   //How much traning samples
const int WINDOW_SIZE = 2048;  //How long is each sample
const int BATCH_SIZE = 16;     //How many samples per batch
const int NUM_EPOCHS = 2048;   //How much epoch we want to run

int main()
{

  //Create a sample buffer
  std::vector<td::vec_t> samples(SAMPLE_NUM, td::vec_t(WINDOW_SIZE));

  AudioFile<float> audioFile;
  audioFile.load("a.wav"); //Load audio
  auto& data = audioFile.samples[0]; //Just use the first channel

  //Create a RNG and a distribution to generate random numbers
  std::mt19937 rng;
  std::uniform_int_distribution<int> dist(0, data.size()-WINDOW_SIZE);
  //Generate samples
  for(auto& v : samples)
  {
    int offset = dist(rng);//Generate random offsets
    auto start = data.begin() + offset;
    //Copy data from source to sample
    std::copy(start, start+WINDOW_SIZE, v.begin());
  }
  
  //Create an autoencoder
  td::network<td::sequential> net;
  net << td::fully_connected_layer(WINDOW_SIZE, 512) << td::tanh_layer()
    << td::fully_connected_layer(512, WINDOW_SIZE);
  
  //Helper class
  td::progress_display disp(SAMPLE_NUM);
  td::timer t;
  
  int currentEpoch = 0;
  
  //Callbacks when a mini bactch is done
  auto onMinibatch = [&]()
  {
    //This updates the progress display
    disp += BATCH_SIZE;  
  };
  
  //Callbacks when an epoch is done
  auto onEpoch = [&]()
  {
    std::cout << "Epoch " << ++currentEpoch << "/" << NUM_EPOCHS << "done. "
      << t.elapsed() << "s elapsed." << std::endl;
      
    //Reset progress display and timer
    disp.restart(SAMPLE_NUM);
    t.restart();
  };
  
  //train the network with absolute(L1) error.
  td::adagrad optimizer;
  net.fit<td::absolute>(optimizer, samples, samples, BATCH_SIZE, NUM_EPOCHS
    , onMinibatch, onEpoch);
  net.save("net");

  //Let's try the network
  std::vector<float> result(data.size());
  for(int i=0;i<data.size();i+=WINDOW_SIZE)
  {
    //Input to the neural network
    td::vec_t input(WINDOW_SIZE);
    //copy data into the input vector
    std::copy(data.begin()+i, data.begin()+i+WINDOW_SIZE, input.begin());

    //Run the neural network then copy it to the result buffer
    td::vec_t predict = net.predict(input);
    std::copy(result.begin()+i, result.begin()+i+WINDOW_SIZE, predict.begin());
  }
  
  //Save the audio we ganarated
  AudioFile<float> saveFile;
  AudioFile<float>::AudioBuffer buffer(1);
  buffer[0] = result;
  audioFile.setAudioBuffer(buffer);
  audioFile.save("audioFile2.wav");
}
コンパイル
g++ auto_encoder.cpp -I . -std=c++14 AudioFile.cpp
実行
...

0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Epoch 336/2048done. 40.7405s elapsed.

0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Epoch 337/2048done. 42.2788s elapsed.

...
wavファイルによると思うが、3日ぐらいかかりそうな勢い

tiny-dnn で遊ぼ (XOR)

チュートリアル XOR
#include <tiny_dnn/tiny_dnn.h>
#include <vector>

namespace td = tiny_dnn;
namespace tda = tiny_dnn::activation;

int main() {
  td::network<td::sequential> net;
  net << td::fully_connected_layer(2,3) << td::sigmoid_layer()
  << td::fully_connected_layer(3,1) << td::sigmoid_layer();

  std::vector<td::vec_t> trainIn = {{0,0}, {0,1}, {1,0}, {1,1}};
  std::vector<td::vec_t> trainOut = {{0}, {1}, {1}, {0}};

  td::gradient_descent optimizer; //(0.53);
  optimizer.alpha = 0.53f;
  net.fit<td::mse>(optimizer, trainIn, trainOut, 1, 1000);
  net.save("net");
  std::cout << net.predict({0,0})[0] << std::endl;
  std::cout << net.predict({0,1})[0] << std::endl;
  std::cout << net.predict({1,0})[0] << std::endl;
  std::cout << net.predict({1,1})[0] << std::endl;

  return 0;
}
出力
0.0411867
0.956243
0.959534
0.037655