TensorFlowで二次方程式を解く。

今度は二次方程式を同様の方法で解いてみる。

# 方程式の解を求める。
# y = a*x^2+b*x+c において、y=0となるxを求める。
# xをVariableとし学習対象とする。
# 係数a,b,cは定数とする。

import tensorflow as tf


#-------------------------------------------
# モデル定義
a = tf.constant(1.0, name="const_a")
b = tf.constant(-5.0, name="const_b")
c = tf.constant(6.0, name="const_c")
x = tf.Variable(0.0, name="val_x")

y = a * tf.square(x) + b * x + c

# 評価用変数
# 求めたいのはy = 0となる状態であるが、
# minimize(y) とすると、y が0超えて負数をどこまでも降りてしまうため、
# 自乗し、0に収束していくようにする。
loss = tf.square(y)

tf.summary.scalar("x", x)
tf.summary.scalar("y", y)
tf.summary.scalar("loss", loss)

# 訓練
train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

# 初期化
init = tf.global_variables_initializer()

summary_op = tf.summary.merge_all()

#-------------------------------------------
# 実行

with tf.Session() as sess:
  summary_writer = tf.summary.FileWriter("log", sess.graph)
  sess.run(init)

  for i in range(100):
    sess.run(train)
    print(sess.run(x))
    summary_str = sess.run(summary_op)
    summary_writer.add_summary(summary_str, i)

ここではxの初期値を0.0としている。
この場合、100回実行後のxの値は1.9667124となった。
一方、xの初期値を5.0とした場合は3.033287となった。

y = x^2 -5*x + 6 を解析的に解いた場合はx = 2, 3 と2つの解を持つ。
二次曲線をどちら側から近づいていくかによって、求められる解が変わってくる。

ちなみに初期値を2.5 (2つの解の中間値、二次曲線が極小となるxの値)とすると、
実行結果は2.5のまま変化がなかった。
多分、勾配降下法で勾配(gradient)を取るとx=2.5の点では0ベクトルとなるので
勾配の方向に進むということができなかったのではないかと思われる。

TensorFlowで一次方程式を解く。

TensorFlowを用いて一次方程式(y=a*x+b)の解を求めてみる。TensorFlowを使わなくても解析的に簡単に解は出せるが、
あえてTensorFlowで訓練させた結果として解を出してみる。

TensorFlowで y = a*x + b のグラフを作り、yが0になるように学習を行う。

# 方程式の解を求める。
# y = ax+b において、y=0となるxを求める。
# xをVariableとし学習対象とする。
# 係数a,bは定数とする。

import tensorflow as tf

#-------------------------------------------
# モデル定義
a = tf.constant(2.0, name="const_a")
b = tf.constant(3.0, name="const_b")
x = tf.Variable(10.0, name="val_x")
y = a*x + b

# 評価用変数
# 求めたいのはy = 0となる状態であるが、
# minimize(y) とすると、y が0超えて負数をどこまでも降りてしまうため、
# 自乗し、0に収束していくようにする。
loss = tf.square(y)

tf.summary.scalar("x", x)
tf.summary.scalar("y", y)
tf.summary.scalar("loss", loss)


# 訓練
train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

# 初期化
init = tf.global_variables_initializer()

summary_op = tf.summary.merge_all()


#-------------------------------------------
# 実行

with tf.Session() as sess:

  summary_writer = tf.summary.FileWriter("log", sess.graph)

  sess.run(init)

  for i in range(100):
    sess.run(train)
    print(sess.run(x))
    summary_str = sess.run(summary_op)
    summary_writer.add_summary(summary_str, i)

実行結果、100回ループ後のxの値は -1.497249 となった。
学習率を上げれば、もっと早く、-1.5になる。

ubuntu18.04でWI-U2-433DHPを有効にする。

ubuntuのバージョンを16.04から18.04にアップデートするとUSB無線LAN(WI-U2-433DHP)が認識されなくなってしまった。
16.04のときにインストールしたドライバをmakeするとエラーが出るようになってしまった。

[1]https://qiita.com/diescake/items/2370dc67a0ed40b089ba
を参考に
[2]https://github.com/gnab/rtl8812au/
からドライバをダウンロードする。

$ git clone https://github.com/msharov/rtl8812au.git

名前が8812になっているが8821も対応している模様。
ダウンロードしてrtl8812auの中に入り、ビルドする。

$ make

そして、インストール

$ sudo insmod 8812au.ko

エラーは出なかったが、ドライバは依然認識されない。
gitから落としたドライバがWI-U2-433DHPに対応していなかった模様。

先ず、WI-U2-433DHPのデバイスIDを調べる。WI-U2-433DHPをUSBポートに挿した状態で、

$ lsusb

・・・
Bus 001 Device 002: ID 0411:029b BUFFALO INC. (formerly MelCo., Inc.)
・・・

と表示されたので

/os_dep/linux/usb_intf.c を開き、
#ifdef CONFIG_RTL8821Aの箇所を見ると、確かに該当するデバイスIDが含まれていない。
そこに

{USB_DEVICE(0x0411, 0x029B),.driver_info = RTL8821},

を追加。
もう一度、

$ make
$ sudo insmod 8812au.ko

とすると、デバイスが認識された。

    • -

ついでにREADME.mdに従い、DKMSをインストールし組み込んでおく。
以前はアップデートの旅にドライバを再度ビルド、インストールする必要があったが
おそらく、DKMSが自動でやってくれるはず。

WI-U2-433DHP

BaffaloのWiFiドングルWI-U2-433DHPをUbuntu16.04で使えるようにした。
USBに刺しただけでは使えない。
Realtekのドライバを落としてきて、ビルドして組み込む必要がある。
参考にしたサイト
[1] http://kawauso-festival.blogspot.jp/2017/01/buffalowi-u2-433dhpubuntu1404.html
[2] https://stackoverflow.com/questions/40515929/building-drivers-yields-error-void-value-not-ignored-as-it-ought-to-be

上記[1]の通りやったが、makeでビルドエラーが出る。[2]を参考に2箇所ほど
ソースの修正を行うとビルドが通った。

    • -

一旦WiFiドングルを抜いて(別のところに挿して)起動すると認識しない。USBの挿す場所を戻しても認識しなくなってしまった。
どういう状態にあったのかは不明であるが、再度上記[1]を参考にmakeからやり直したら再度認識された。

$ make
$ sudo make install
$ sudo modprobe 8821au

Threadの使い方

C++ std11で追加されたThreadの使い方。
std::threadで関数、関数オブジェクトを渡せば、その関数を別スレッドで実行してくれる。
終わった後にdetachやjoinをしておかないと、コアダンプしてしまう。
下の例では、無名関数オブジェクトを作って渡している。

//test.cpp
// $ g++ -std=c++14 -pthread test.cpp

#include <iostream>
#include <thread>

class Cell
{
  int _id;
public:
  Cell(int id)
  {
    _id = id;
  }

  void run(void)
  {
    std::thread cellThread([&]{
	while(1){
	  std::cout << "Cell Thread : " << _id << std::endl;
	  std::this_thread::sleep_for(std::chrono::seconds(1));
	}
      });
    cellThread.detach();
  }
  
};

int main()
{
  std::cout << "Hello test.cpp" << std::endl;

  Cell *c1 = new Cell(1);
  Cell *c2 = new Cell(2);
  Cell *c3 = new Cell(3);

  c1->run();
  c2->run();
  c3->run();

  while(1){
    std::cout << "main loop : " << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

emacs上でのgdbの使い方


# 対象となるプログラムは -g オプションでデバッグシンボルを生成させておく。
# emacs上で以下入力
M-x gdb

Run gdb (like this): gdb
# と聞かれたら、

Run gdb (like this): gdb -i=mi a.out
# (デバッグしたいバイナリがa.outの場合)
# gdbemacs上で起動する。(gdb)のプロンプトが表示されるので

(gdb) b main
# でブレークポイントをmain()に設定。

(gdb) r
# でブレークを張ったmain()まで実行される。

(gdb) n # ステップオーバ
(gdb) s # ステップイン
(gdb) c # 実行継続