2018年8月27日月曜日

画像処理の演習を Python3 用の OpenCV3 / OpenCV4 で実行する方法

0. はじめに

Pythonにはバージョン2 (Python2) とバージョン3 (Python3)の2系統があります。本書のプログラムは、原則的に両方のバージョンで実行できるように記述しています。

しかし、画像処理に用いるライブラリOpenCVだけは、Python2用とPython3用のインストール方法が全く異なることから、Python2での利用に限定していました。2018年8月の時点のRaspbian Stretchで、Pythonがバージョン2.7.13、OpenCVはバージョン2.4.9.1でした。

しかし、Python3でOpenCVを用いる方法が容易になってきましたので、Python3で本書のOpenCVを用いたプログラムを実行する方法をここで紹介することにしました。以下のインストール方法は2020年3月に確認しました。

1. 準備

まず、本書の10章までにインストールした各種ツールをPython3用にあらかじめインストールしておきます。下記の3つの命令を順に実行します。
sudo apt update
sudo apt install python3-sklearn python3-pil.imagetk mpg321 liblapack-dev libhdf5-dev python3-h5py
sudo pip3 install keras==2.3.1 theano
このあとは、用いているOSと利用したいOpenCVのバージョンによりコマンドが分かれます。

2. Rasppbian Buster または Bullseye + Python3 + OpenCV3 の場合

Raspbian Buster または Bullseye をお使いの場合、apt コマンドでインストールできるOpenCV3をインストールするのが最も簡単ですのでお勧めです。

下記のようにOpenCVをインストールします。
sudo apt install python3-opencv
以上で、Python3 用の OpenCV のインストールが終わりました。

2019年6月の時点で、Python3はバージョン3.7.3、OpenCV はバージョン3.2.0となりました。

3. Rasppbian Buster + Python3 + OpenCV4 の場合

Raspbian Busterをお使いの場合、pip3 コマンドでインストールするとOpenCV4がインストールされます。インストール中のネットワークトラブルによるエラーが多いので、上級者向けと考えています。

まず、必要なパッケージをインストールします。
sudo apt install libatlas-base-dev libjasper-dev libqtgui4 libqt4-test
最後に、Python3 用の OpenCV4 をインストールします。
sudo pip3 install opencv-python==4.5.1.48
最後に、以下のコマンドを実行します。それが終わったらRaspberry Piを再起動します。
echo "export LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1" >> ~/.bashrc
以上で、Python3 用の OpenCV4 のインストールが終わりました。

なお、OpenCVのバージョンを 4.5.1.48 に指定している理由は、それ以降(4.5.3 など) では NumPy の新しいバージョン (1.21 など) を要求されるためです。
NumPy 1.20 以降では、機械学習用のライブラリ TensorFlow 2.x の動作に問題が出る場合があるため、Numpy 1.19 で使える OpenCV 4.5.1.48 を指定しているのです。
TensorFlow 2.x を使わない場合は OpenCV のバージョン指定は不要ですが、利用は自己責任でお願いします。

なお、Raspberry Piでのpip(pip3)を用いたツールのインストールは、ネットワークのトラブルにより失敗することが多いようです。例えば、pip(pip3)コマンドを実行したときに下記のような40行程度のエラーが出ることがあります。
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
(中略)
  File "/usr/share/python-wheels/urllib3-1.19.1-py2.py3-none-any.whl/urllib3/util/retry.py", line 315, in increment
    total -= 1
TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'
これは、インストール時のネットワークに問題があるときに出るエラーです。 Raspberry Piがネットワークに接続していないとき、および、ファイルのダウンロード元であるサーバーに問題があるときの両方で上記エラーが出ます。
あるいは、同様のエラーで
THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE.
と出る場合もあります。

Raspberry Piのネットワーク接続に問題がある場合はその改善を試みてください。
一方、先方のサーバーに問題がある場合、時間をあけてからコマンドを再実行すると問題が解消される場合があります。Raspberry Pi上でpipを用いてツールをインストールする場合、サーバー側の問題なのか、何度もインストールを試みて初めてインストールに成功する、ということが多い印象があります。

4. Rasppbian Stretch + Python3 + OpenCV4 の場合

Raspbian Stretch上のPython3でOpenCV4を用いたい場合、以下のようにします。

まず、必要なパッケージをインストールします。
sudo apt install libatlas-base-dev libjasper-dev libqtgui4 python3-pyqt5 libqt4-test
次に、Python3 用の OpenCV4 をインストールします。
sudo pip3 install opencv-python
以上で、Python3 用の OpenCV4 のインストールが終わりました。

2018年8月26日日曜日

人間の手を予測するじゃんけんシステムにロボットハンドを追加する

0. はじめに

本書では、9章および10章において、コンピュータと勝負できるじゃんけんシステムを作成しました。

過去の履歴をもとに人間の手を予測する部分をパーセプトロンで、画像処理と組み合わせて人間の現在の手を読み取る部分に三層ニューラルネットワークやディープラーニングの畳み込みニューラルネットワーク (CNN) を用いました。

このシステムでは、コンピュータの出す手はディスプレイ上の画像として表現されていました。本ページでは、コンピュータの出す手をロボットハンドに表現させる手法を紹介します。

実際にそのシステムが稼働している様子を示したのが下図です。左側に見えている黒い物体がロボットハンドです。後述しますが、ここでは市販のものを用いています。


本システムが動作している様子は以下の動画に示されています。


本書のあとがきで「本書をきっかけに機械学習の機能を組み込んだ電子工作の作品作りにチャレンジするのも面白いでしょう」と記しました。このシステムはまさにそのような例になっています。完成までの時間を短縮するために市販のロボットハンドを用いましたが、これを自作のものにすれば、より独自性の高い作品となるでしょう。

以下では、このロボットハンドを追加したじゃんけんシステムの概要と仕組みを解説します。

1. 本システムの構成(ロボットハンド編)

今回、なるべく簡単にシステムを実現するため、ロボットハンドは下図の市販のものとしました。


これは、アマゾンで購入した下記の商品です。
選ぶときに考慮したのは、全ての指を独立にプログラムにより制御できることです。このロボットは5本の指を5つのサーボモーターで曲げ伸ばしするだけなので、サーボモーターの制御により自由に動かせることから選択しました。

なお、このロボットハンドはものを掴めるわけではない上に高価なので、このじゃんけんシステムのためだけに購入するのは現実的ではないでしょう。5つのサーボモーターを用いて簡易的な手を自作するのが良いかもしれません。

参考までに、このロボットハンドを構造を記します。5つのサーボモーターは全て手首よりの下の部分にあり、シャフトで動力を伝えて上部の指を曲げ伸ばししています。


このロボットには第一関節、第二関節があり、サーボモーターの動きと連動する仕組みになっています。この仕組みをそのまま自作で再現するのはそれなりに大変ですが、第一関節と第二関節のない5本の棒を曲げるだけなら比較的簡単に実現できるかもしれません。

サーボモーターを用いた工作は「実例で学ぶRaspberry Pi電子工作」の6脚ロボットの作成で取り扱いましたので、興味のある方はご参考ください。

ただし、電子工作に触れるのは初めてという方は、入門編である「カラー図解 最新 Raspberry Piで学ぶ電子工作」から学び始めるのが無難でしょう。

本ページの以下の内容は、ある程度電子工作に慣れている方向けの解説となっておりますのでご了承ください。

2. 本システムの構成(回路編)

このロボットハンドを制御するための回路部分が下図に示されています。このうち、Raspberry Piとカメラモジュールは本書で解説済のものです。


5本の指を制御するために追加しているのが、上図の「PCA9685搭載サーボドライバー」です。これは「実例で学ぶRaspberry Pi電子工作」の8章で6脚ロボットを制御する際に用いたもので、複数のサーボモーターを制御するためのものです。

スイッチサイエンスさんで購入できる「PCA9685搭載16チャネル PWM/サーボ ドライバー (I2C接続)」を用いています。

Raspberry Piとの接続は下図のようになっています。これもまた「実例で学ぶRaspberry Pi電子工作」の8章で用いた接続とほぼ同じです。

なお、ロボットハンドに供給する電源としては秋月電子通商さんで購入できる「スイッチングACアダプター6V2A」を用いました。ロボットハンドに7.5Vのアダプタが付属するのですが、PCA9685搭載サーボドライバーに接続できる最大の電圧が6Vであるため変更しました。なお、アダプターを接続するソケットはロボットハンドに付属するものが利用できます。



3. 本システムの構成(プログラム編)

このシステムを動作させるためには、I2Cと呼ばれる通信方法を有効にする必要があります。メニューの「設定」→「Raspberry Piの設定」で設定アプリケーションを起動し、「インターフェイス」タブを選択し、「I2C」の項目を「有効」にしてください。

次に、このシステムを動作させるためのプログラム janken-robothand.py をダウンロードします。これは、ディープラーニング用である ml-10-09-janken-deep.py をベースに作成しました。

まずターミナルを起動してください。ml-10-09-janken-deep.py がユーザーpiのホームに直接存在する場合は、そのまま下記のコマンドを実行して janken-robothand.py をダウンロードしてください。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/janken-robothand.py
もし、ml-10-09-janken-deep.py が bluebacks ディレクトリ内にある場合は、上記コマンドを実行する前に「cd bluebacks」コマンドを実行してください。

ダウンロードが終わったら、下記のコマンドで実行します。これは ml-10-09-janken-deep.py の実行方法と同じですね。
python janken-robothand.py ml-hand-cnn.h5
うまくいけば、ロボットハンドつきのじゃんけんシステムが動作します。

なお、「本書のディープラーニングの演習をkeras + TensorFlowで実行する方法」をもとにkerasのバックエンドをTensorFlowにしている方は、上記プログラムは動作しません。TensorFlow用のファイルを下記でダウンロードし、
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/janken-robothand-tf.py
下記コマンドで実行するようにしてください。
python janken-robothand-tf.py ml-hand-cnn.h5

さて、本ページと同じ市販のロボットハンドを用いる場合は上記のプログラムの実行で良いのですが、ロボットハンドを自作した場合は調整が必要です。以下ではそのためのコメントをいくつか記します。

まず、ロボットハンドを動かすための命令は janken-robothand.py 内の下記の部分(guchokipa_servo関数)です。
def guchokipa_servo(i):
    if i==0: #グーのとき
        # 順に、親指~小指に対応するサーボの値。
        # 2番目の引数は常に0。範囲は143~410程度で276がゼロ点。
        # 以下同様。
        setPCA9685Duty(0, 0, 350)
        sleep(0.01)
        setPCA9685Duty(1, 0, 220)
        sleep(0.01)
        setPCA9685Duty(2, 0, 240)
        sleep(0.01)
        setPCA9685Duty(3, 0, 220)
        sleep(0.01)
        setPCA9685Duty(4, 0, 350)
    elif i==1: #チョキのとき
        setPCA9685Duty(0, 0, 350)
        sleep(0.01)
        setPCA9685Duty(1, 0, 380)
        sleep(0.01)
        setPCA9685Duty(2, 0, 360)
        sleep(0.01)
        setPCA9685Duty(3, 0, 220)
        sleep(0.01)
        setPCA9685Duty(4, 0, 350)
    elif  i==2: #パーのとき
        setPCA9685Duty(0, 0, 190)
        sleep(0.01)
        setPCA9685Duty(1, 0, 380)
        sleep(0.01)
        setPCA9685Duty(2, 0, 360)
        sleep(0.01)
        setPCA9685Duty(3, 0, 360)
        sleep(0.01)
        setPCA9685Duty(4, 0, 210)
引数として与えるiが0(グー)、1(チョキ)、2(パー)のときの、5つのサーボモーターに与える数値が定められています。 例えば、グー(i=0)のとき、親指から小指のサーボモーターに与えられる数値は、順に(350, 220, 240, 220, 350)となっています。

コメントにありますように、ここに与える数値は143~410程度で276がサーボモーターのゼロ点となっています。この数値は、ロボットハンドのつくり方によってまったく異なります。ですから、ロボットハンドごとに値を変更する必要があります。

しかし、じゃんけんシステムが動作しているときにこの数値を変更するのは困難です。そこで、数値調整のためのテストプログラム  janken-robothand-test.py を作成しました。下記のコマンドを実行してダウンロードしましょう。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/janken-robothand-test.py
このプログラムの実行方法は下記の通りです。
python janken-robothand-test.py 0
python janken-robothand-test.py 1
python janken-robothand-test.py 2
1つめの命令を実行すると、ロボットハンドは「グー」の形で静止します。2つ目なら「チョキ」、3つ目なら「パー」です。

このプログラム janken-robothand-test.py 内にも上と同じguchokipa_servo関数は存在します。そこで、 janken-robothand-test.py の guchokipa_servo関数を編集して「グー」、「チョキ」、「パー」の形に対応するサーボモーター用の数値を確定し、その数値の変更を janken-robothand.py 内のguchokipa_servo関数にも適用すれば良いのです。

あともう一点注意すべき箇所があります。 janken-robothand.py に下記の部分があります。
(中略)
    # "ぽん!"のタイミングでサーボが動くようタイミング調整
    sleep(2)
    # サーボを動かす
    guchokipa_servo(comp_choice)

    # サーボの動きはじめと手の描画のタイミング調整
    sleep(0.2)
(中略)
ここにある「sleep(2)」と「sleep(0.2)」は待ち時間を設定している部分ですが、これもロボットハンドにより調整が必要だろうと思います。

一つ目の「sleep(2)」は「じゃんけんぽん」という掛け声が始まってから何秒後にサーボモーターが動き始めるか、を設定しています。これを適切に調整して「ぽん!」の掛け声と同時にロボットハンドが動き始めるようにします。

二つ目の「sleep(0.2)」は、サーボモーターが動き始めてから何秒後に人間の手を確定させるか、を調整しています。この値が小さいと、まだ人間が手を出し切る前に手を読み取ってしまうので、誤認識が多くなるでしょう。

4. おわりに

以上、ロボットハンドを用いたじゃんけんシステムについて紹介しました。実際にこのシステムを作ろうとすると、高価なロボットハンドを購入するか、あるいは自作するかの選択となりますが、いずれにせよハードルは低くはありません。

しかし、動画を見ることで「機械学習と電子工作を組み合わせることで何ができるか」のイメージはつかめたのではないかと思います。

皆さんも、機械学習と電子工作を組み合わてどのようなシステムが可能か考えてみると楽しいでしょう。

2018年8月21日火曜日

手描き数字認識をTensorFlow.jsによりブラウザで実行してみよう

0. はじめに

本書の機械学習用プログラムは、Pythonというプログラミング言語に機械学習用のライブラリを組み合わせて実現しています。ディープラーニングにはkerasとtheano、それ以外はscikit-learnを用いたのでした。

また、ディープラーニングの計算を担う部分であるtheanoは、ライブラリkerasのバックエンドと呼ばれるのでした。

書籍に記したように、このバックエンドは変更可能です。2018年8月に投稿した下記のページでは、theanoをGoogleの開発したTensorFlowに置き換えて本書の演習プログラムを実行する方法を解説しました。
上記のページに従うと、TensorFlowをプログラミング言語Pythonで利用することになります。

一方、TensorFlowをJavaScriptというプログラミング言語から利用可能になるTensorFlow.jsが2018年4月に公開されました。このTensorFlow.jsを用いると、皆さんが普段お使いのブラウザでディープラーニングを実行できるようになります。

本ページではその簡単な例を試してみましょう。

1. 実行してみよう

それでは、下記のリンクをクリックし、TensorFlow.jsによるプログラムを体験してみましょう。
現れたウインドウには、下図のように3つの枠と2つのボタンがあり、マウスやタッチにより描いた0~9の数字を認識できるようになっています。「認識」ボタンをクリックまたはタッチすることで結果が表示されます。


本書をお読み頂いた方なら気づくかもしれませんが、これは演習プログラム ml-10-06-digits-cnn-gui-mod.py を JavaScript + TensorFlow.js に移植したものになっています。このプラグラムがどのような仕組みで動いているかの解説は、本書の6章と10章をお読みください。

ブラウザで動作するプログラムですので、下図のようにタブレット上のタッチでも数字を描くことができます。

ただし、プログラムページにも表示されているように、動作するブラウザはChrome、Firefox、Microsoft Edge、Safariの最新版です。これらのブラウザの古いバージョンでは動作しない可能性がありますし、Internet Explorerでは動作しませんのでご注意ください。


2. 何に使えるの?

さて、Raspberry Pi上のPythonプログラムとほぼ同じプログラムをブラウザで動作させることができることが体験頂けたと思います。

この仕組みは、学習結果をデモンストレーションする用途で利用するのが効果的です。

本書で体験できるように、機械学習の学習のプロセスは、Raspberry Piに代表されるようなLinux系OS上で実行するのが一般的です。試行錯誤を繰り返し、良い学習結果が得られることを目指します。

良い学習結果が得られたら、やはりLinux系OS上で結果を確認することができます。 それが本書の演習プログラム ml-10-06-digits-cnn-gui-mod.py なのでした。

一方、その学習結果をブラウザ上で実行できたら、より多くの人にその成果を体験してもらえるでしょう。最新のブラウザがあれば、ツールを追加インストールする必要もなく、結果を追体験できるのですから。

以上のように、学習結果のデモンストレーションとして用いるのが TenforFlow.js の典型的な使用例と言えるのではないでしょうか。

あるいは、学習結果を利用したインターネット上のサービスを作ることもできるでしょう。

さて、この例を体験すると、学習結果の確認はPythonではなくJavaScriptによりブラウザで出来た方が良い、と思う方もいるかもしれません。

しかし、PythonとJavaScriptというのは全く異なる言語ですから、PythonプログラムをJavaScriptプログラムに移植することは、実際にはかなりの労力が必要となります。

ですので、本ページの内容は「皆さんに体験して頂く」ことを主眼とし、皆さんがJavaScriptプログラムを書けるようになることを目指すわけではありません。ご了承ください。

3. 少しだけ技術的なコメント

少しだけ技術的なコメントを記しますが、本ページのプログラムを体験するために以下の内容を理解する必要はありませんので、飛ばして頂いても全く問題ありません。

JavaScriptプログラム自体は、プログラムのページでソースを閲覧すると確認することができます。基本的な流れは、
  1. 学習済のデータを読みこみ、ネットワークモデルを構築する
  2. モデルに手書き数字に基づいた入力を与え、結果を確認する
となっています。

学習済のデータは、本書では ml-digits-cnn.h5 という拡張子h5のファイルでした。これを、「Importing a Keras model into TensorFlow.js」に従い、jsonという形式のファイルに変換しました。

具体的には、tensorflowjsを下記のコマンドでインストールし、
sudo pip install tensorflowjs
その後、下記のコマンドでh5ファイルをjsonファイルに変換しました。
tensorflowjs_converter --input_format keras ml-digits-cnn.h5 .
すると、実行したディレクトリにmodel.json、group1-shard1of1、group2-shard1of1、group3-shard1of1、group4-shard1of1 というファイルが出来ていますので、これをサーバー上に置きます。

なお、用いるh5ファイルは、keras + TensorFlowで出力したものでなければならないようです。本書に付属するh5ファイルはkeras + theanoで出力したものですから、そのままでは正しい認識結果を返しませんでした。

さて、作成した学習済jsonファイルを読み込むのは、下記のようなJavaScriptです。model.jsonを読み込むことで、group1-shard1of1、group2-shard1of1、group3-shard1of1、group4-shard1of1も自動的に読み込まれます。
async function load_tf(){
  model = await tf.loadModel('http://アドレス/model.json');
}
ファイルの読み込みによりモデルを構築したら、下記の命令により数字の認識結果を取得しています。例えば数字の2が認識された場合、argMax(1)により、[2]という配列(テンソル)が得られますので、その中身の数字をget(0)で取得してます。
var result = model.predict(X).argMax(1).get(0);

なお、おまけですがアヤメの分類をおこなうプログラム ml-10-02-iris-deep-load.py のTensorFlow.js 版も下記のリンクで見ることができます。
こちらは見て面白い例ではありませんが、シンプルなJavaScriptのソースを見たい方には参考になるかもしれません。

2018年8月9日木曜日

本書のディープラーニングの演習をkeras + TensorFlowで実行する方法

はじめに

本書では、10章のディープラーニングの演習のためにkerasというライブラリとTheanoというバックエンドを組み合わせて用いました。

kerasと組み合わせることができるバックエンドは他にもGoogleのTensorFlowなどがあることを書籍で紹介しましたが、執筆当時TensorFlowはインストールがやや難しいため、本書では用いませんでした。

しかし 2018年8月、TensorFlowのバージョン1.9.0がRaspberry Piを正式にサポートしたことにより、Raspberry PiでTensorFlowを用いることができるようになりました。それにより、本書の10章のプログラムを TensorFlow で実行することが一時的に容易になったのです。

とは言え、この分野は進歩のスピードが速く、状況は常に変わっています。2023年現在、TensorFlow バージョン 2 の Raspberry Pi の公式なサポートはなく、有志の方がビルドしてくださった TensorFlow を利用させて頂いております。
また、ディープラーニングのライブラリのトレンドは TensorFlow から Facebook により開発された PyTorch (パイトーチ) に移り、一方 Google は TensorFlow とは別に jax/flax という数値計算およびディープラーニングのライブラリの開発を始めています。

このように、進歩の激しい分野で最新のツールを追いかけることはなかなか難しいことです。

本ページは、本書 10 章の演習を keras + TensorFlow で実行する方法を解説します。
上で述べたようにライブラリ(すなわちツール)のトレンドは移り変わるものですから、TensorFlow で実行すること自体が重要だというわけではありません。 しかし、2023年10月、Raspberry Pi OS の最新版 Bookworm では、これまで 5 年間用いてきた keras + Theano が動作しなくなってしまいました。 Bookworm で 10 章の演習を実行するには本ページの方法が唯一の方法となってしまったのです。ただし、64-bit 版 OS 限定の方法であることはご了承ください。

状況を整理すると下記の通りです。

OSTensorFlowkeras + Theano
Raspberry Pi OS Bookworm 32-bit××
Raspberry Pi OS Bookworm 64-bit〇 (ver2)×
Raspberry Pi OS Bullseye 32-bit×
Raspberry Pi OS Bullseye 64-bit〇 (ver2)
Raspberry Pi OS Buster 32-bit〇 (ver1, 2)


何が変わるのか?

まず、TensorFlowの実行方法を解説する前に、TheanoからTensorFlowに変えることで何が変わるのかをあらかじめ紹介しておきましょう。

[性能]
  • TheanoからTensorFlowに変えても、計算を担うライブラリが変わるだけですから、機械学習の性能は変化しません
[プログラム全般に関して]
  • Theanoでは、プログラムの初回実行時にコンパイルという作業が行われるため、Raspberry Piで5分程度の時間がかかりました。TensorFlowではこれがなくなり、速やかに計算が始まります
[学習用プログラムに関して]
  • 学習用プログラム(ml-10-01-iris-deep-learn.py、ml-10-03-digits-cnn-learn.py、ml-10-07-hand-cnn-learn.pyの3つ)をRaspberry Pi 2~4で実行すると、マルチコアのプロセッサが有効に使われるため、プログラムの実行時間が短くなります。特に、Raspberry Pi 4 ではかなり高速に学習が終了します(あくまで本書執筆時に用いた Theano による結果と比べれば、ですが)。ただし、結果確認用プログラムではその効果はありません。また、シングルコアのRaspberry Pi 1 やRaspberry Pi Zeroでもその効果はありません。
[その他の注意]
  • TensorFlowをインストールすると、ベクトル計算用のライブラリNumPyがアップグレードされることで、プログラム実行時にライブラリ間のバージョンの組合せに起因する警告(FutureWarningやRuntimeWarningなどのWarning)がでることがあります。Warningはエラーではありませんから、当面は気にしなくても良いのですが、気になる方は気になるでしょう。

以下の流れ

さて、本ページでは以下の流れにそって解説していきます。自分の該当する部分をご覧ください。

TensorFlow 2 系のインストール方法 (Bookworm 64-bit 版のみ)

Raspberry Pi OS Bullseye 64-bit 版で、TensorFlow 2 系のパッケージをインストールするには、以下の8個のコマンドを順に実行します。 PINTO0309 (Katsuya Hyodo) さんのビルドした TensorFlow 2.12 の 64-bit 版がインストールされます。
sudo apt install libhdf5-dev libc-ares-dev libeigen3-dev gcc gfortran libgfortran5 libatlas3-base libatlas-base-dev libopenblas-dev libblas-dev liblapack-dev cython3 libatlas-base-dev openmpi-bin libopenmpi-dev python3-dev python3-h5py

sudo pip3 install keras_applications==1.0.8 --no-deps --break-system-packages

sudo pip3 install keras_preprocessing==1.1.2 --no-deps --break-system-packages

sudo pip3 install numpy==1.24.4 --break-system-packages

sudo pip3 install pybind11==2.9.2 --break-system-packages

pip3 install -U --user six wheel mock --break-system-packages

wget https://github.com/PINTO0309/Tensorflow-bin/releases/download/v2.12.0rc0/tensorflow-2.12.0rc0-cp311-none-linux_aarch64.whl

sudo -H pip3 install tensorflow-2.12.0rc0-cp311-none-linux_aarch64.whl --break-system-packages
全てのコマンドが無事終了すれば インストールは終わりです。なお、TensorFlow 2.3 以降では keras は TensorFlow 専用となっていますので、.keras/keras.json による設定は必要ありません。

インストール終了後、カメラを用いない演習は、本書のサンプルファイルをそのまま利用できます。
カメラを用いた演習を行う場合、本書のサンプルプログラムがそのまま動作するわけではなく、対応済ファイルを別途ダウンロードして利用することになります。 「本書の演習を picamera2 (libcamera) で実行する方法」で配布しているサンプルファイルを利用してください。なお、2023年1月に発売された Camera Module v.3 はこの手法でしか使えません。


TensorFlow 2 系のインストール方法 (Bullseye 64-bit 版のみ)

Raspberry Pi OS Bullseye 64-bit 版で、TensorFlow 2 系のパッケージをインストールするには、以下の11個のコマンドを順に実行します。 PINTO0309 (Katsuya Hyodo) さんのビルドした TensorFlow 2.9 の 64-bit 版がインストールされます。

なお、下記のコマンドを実行すると、numpy のバージョンが新しくなる関係で theano が動作しなくなりますのでご了承ください。
sudo apt install libc-ares-dev libeigen3-dev gfortran libopenblas-dev libopenblas-base cython3 openmpi-bin 

sudo pip3 install keras_applications==1.0.8 --no-deps

sudo pip3 install keras_preprocessing==1.1.2 --no-deps

sudo pip3 install numpy==1.22.3

sudo pip3 install h5py==3.6.0

sudo pip3 install pybind11==2.9.2

pip3 install -U --user six wheel mock

wget "https://raw.githubusercontent.com/PINTO0309/Tensorflow-bin/main/previous_versions/download_tensorflow-2.9.0-cp39-none-linux_aarch64.sh"

chmod +x download_tensorflow-2.9.0-cp39-none-linux_aarch64.sh

./download_tensorflow-2.9.0-cp39-none-linux_aarch64.sh

sudo -H pip3 install tensorflow-2.9.0-cp39-none-linux_aarch64.whl
全てのコマンドが無事終了すれば インストールは終わりです。なお、TensorFlow 2.3 以降では keras は TensorFlow 専用となっていますので、.keras/keras.json による設定は必要ありません。

インストール終了後、カメラを用いない演習は、本書のサンプルファイルをそのまま利用できます。
カメラを用いた演習を行う場合、Bullseye 64-bit 版では、下記の2通りの選択肢があります。いずれの場合も、本書のサンプルプログラムがそのまま動作するわけではなく、対応済ファイルを別途ダウンロードして利用することになります。 Legacy Camera モードの有効化 / 無効化は下記のページをご覧ください。


TensorFlow 2 系のインストール方法 (Busterまで)

Raspberry Pi OS Bullseye よりも古い Buster までの OS で、Python3 用の TensorFlow 2 系のパッケージをインストールするには、以下の3つのコマンドを順に実行します。
sudo pip3 install keras==2.4.3
wget https://github.com/lhelontra/tensorflow-on-arm/releases/download/v2.4.0/tensorflow-2.4.0-cp37-none-linux_armv7l.whl
sudo pip3 install tensorflow-2.4.0-cp37-none-linux_armv7l.whl
一つ目のコマンドは、kerasを最新の TensorFlow 用にアップグレードしています。この新しい keras は TensorFlow 専用となっており、本書で解説した Theano と合わせて使うことはできませんのでご注意下さい。そのため、Theano を用いるときは keras のバージョンを 2.3.1 に指定していたのでした。

二つ目のコマンドは、lhelontra 氏のサイトから、氏がビルドしたパッケージをダウンロードしています。三つ目のコマンドでそれをインストールしています。

なお、Raspberry Pi 1 や Raspberry Pi Zero を用いる場合、二つ目および三つ目のコマンドの「armv7l」の部分を「armv6l」に変更する必要がありますのでご注意ください。ただし、私は Raspberry Pi 1 や Raspberry Pi Zero での動作は確認していません。

以上でインストールは終わりです。なお、TensorFlow 2.3 以降では keras は TensorFlow 専用となっていますので、.keras/keras.json による設定は必要ありません。

上記のように TensorFlow2 をインストールした場合、学習済ファイルを TensorFlow2 用に更新しないと、認識率が悪くなることがあります。また、プログラムに手を加えなければならない場合もありました。

それらのファイルは下記のコマンドを実行することでダウンロードできます。プログラムをbluebacksディレクトリに展開した方は、下記のダウンロードコマンド実行前に「cd bluebacks」を実行してください。

なお、TensorFlow 2 系では、配布した学習済のファイル(拡張子 h5)も変更が必要な場合があるようでしたので、そちらもダウンロードしています。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/ml-10-09-janken-deep-tf2.py
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/ml-10-10-janken-deep-shorten-tf2.py
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/ml-digits-cnn-tf2.h5
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/ml-hand-cnn-tf2.h5
これらの利用方法は例えば以下となります。ml-digits-cnn-tf2.h5 や ml-hand-cnn-tf2.h5 のように、「-tf2」がついた学習済ファイルが存在する場合はそちらを優先しを用いるようにしてください。ml-iris-dnn.h5 は「-tf2」がついていないファイルを用いて構いません。
python3 ml-10-04-digits-cnn-load.py ml-digits-cnn-tf2.h5
python3 ml-10-05-digits-cnn-gui.py ml-digits-cnn-tf2.h5
python3 ml-10-06-digits-cnn-gui-mod.py ml-digits-cnn-tf2.h5

python3 ml-10-09-janken-deep-tf2.py ml-hand-cnn-tf2.h5
python3 ml-10-10-janken-deep-shorten-tf2.py ml-hand-cnn-tf2.h5


TensorFlow 1 系のインストール方法 (Busterまで)

Raspberry Pi OS Bullseye よりも古い Buster までの OS で、Python3 用の TensorFlow 1 系のパッケージをインストールするには、以下のコマンドを実行します。
sudo pip3 install keras==2.3.1 tensorflow
環境によってはpip3コマンドは下記のようにMemoryErrorで終了してしまうかもしれません。
(中略)
  File "/usr/share/python-wheels/CacheControl-0.11.7-py2.py3-none-any.whl/cachecontrol/filewrapper.py", line 50, in _close
    self.__callback(self.__buf.getvalue())
  File "/usr/share/python-wheels/CacheControl-0.11.7-py2.py3-none-any.whl/cachecontrol/controller.py", line 275, in cache_response
    self.serializer.dumps(request, response, body=body),
  File "/usr/share/python-wheels/CacheControl-0.11.7-py2.py3-none-any.whl/cachecontrol/serialize.py", line 87, in dumps
    ).encode("utf8"),
MemoryError
その場合、下記のように「--no-cache-dir」オプションをつけてインストールコマンドを実行してください。
sudo pip3 --no-cache-dir install keras==2.3.1 tensorflow
インストールは、途中でNumPyのアップグレードが実行されるため、数十分かかります。2018年8月時点で、NumPyのバージョンは1.12.1から1.15.0とアップグレードされました。

なお、下記のようなエラーが出てインストールに失敗することがあります。
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
(中略)
  File "/usr/share/python-wheels/urllib3-1.19.1-py2.py3-none-any.whl/urllib3/util/retry.py", line 315, in increment
    total -= 1
TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'
これは、インストール時のネットワークに問題があるときに出るエラーです。 Raspberry Piがネットワークに接続していないとき、および、ファイルのダウンロード元であるサーバーに問題があるときの両方で上記エラーが出ます。
あるいは、同様のエラーで
THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE.
と出る場合もあります。
まず、Raspberry Piのネットワーク接続に問題がある場合はその改善を試みてください。
一方、先方のサーバーに問題がある場合、時間をあけてからコマンドを再実行すると問題が解消される場合があります。Raspberry Pi上でpipを用いてツールをインストールする場合、サーバー側の問題なのか、何度もインストールを試みて初めてインストールに成功する、ということが多い印象があります。


NumPyがアップグレードされたことは、本書で何度か行ったように、ml-03-01-version.pyを実行すると確認できます。試してみてください。 すると、見慣れない警告(FutureWarningなど)がたくさん現れると思います。

本ページの内容を実行すると、このような警告(Warning)がたくさん出るようになります。以下ではこれらの警告を「気にしない」という方針で記述していきます。これらの警告が気になるという方は、本ページの最後で紹介するツールのアンインストールを実行することで、この警告は出なくなります。

さて、TensorFlowのインストールが終わったら、それをkerasから利用する設定を行いましょう。 本書311ページで行った手順を逆にするだけです。

まず、ターミナルを新規に立ち上げ、下記のコマンドを実行しましょう。
leafpad .keras/keras.json
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。
mousepad .keras/keras.json
すると、下記の内容がテキストエディタleafpadで開きます。本書の演習を実行した方は、backendが下記のようにtheanoに編集されているでしょう。なお、この4行の順番が変わっていることがありますが、それは気にしなくても構いません。
{
    "epsilon": 1e-07,
    "floatx": "float32",
    "image_data_format": "channels_last",
    "backend": "theano"
}
バックエンドをTheanoからTensorFlowにするには、これを下記のように変更します。
{
    "epsilon": 1e-07,
    "floatx": "float32",
    "image_data_format": "channels_last",
    "backend": "tensorflow"
}
編集が終わったら上書き保存し、テキストエディタleafpadを閉じます。以上でTensorFlow 1 系のインストールと設定は終了です。

上記の方法でインストールと設定が終わったら、本書に従いプログラムを実行してみましょう。例えば、手書き数字の認識を行うml-10-06-digits-cnn-gui-mod.pyを実行してみます。
python3 ml-10-06-digits-cnn-gui-mod.py ml-digits-cnn.h5
警告(Warning)はいくつか出ますが、下図のように問題なくプログラムが実行されることがわかります。


おおむね、keras + Theano用のプログラムがそのまま動作しますが、「ml-10-09」および「ml-10-10」から始まるじゃんけんシステムのプログラムだけは、TensorFlow用の変更が必要です(スレッドと呼ばれるものを用いているためです)。

keras + TensorFlow 1 系用のじゃんけんシステムのプログラムは下記の2つのコマンドを実行することでダウンロードできます。プログラムをbluebacksディレクトリに展開した方は、下記のダウンロードコマンド実行前に「cd bluebacks」を実行してください。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/ml-10-09-janken-deep-tf.py
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/ml-10-10-janken-deep-shorten-tf.py
これらのプログラムの実行方法は下記の通りとなります。
python3 ml-10-09-janken-deep-tf.py ml-hand-cnn.h5
python3 ml-10-10-janken-deep-shorten-tf.py ml-hand-cnn.h5


TensorFlowのアンインストール

以上、本書のディープラーニング用プログラムをkeras + TensorFlowの組合せで実行する方法を紹介しました。

これを実行すると、主にNumPyがアップグレードされることにより、ディープラーニングの演習以外でも警告(Warning)が多く出るようになります。

これはインストールしたライブラリの内部記述に起因するものであり、多くはライブラリのアップグレードで解消されることが多いものです。本ページではそれらの警告を「気にしない」という方針で記述しました。

これらの警告が気になるという方は、本ページでインストールしたTensorFlowおよびアップグレードされたNumPyをアンインストールすることをお勧めします。下記のコマンドでアンインストールされます。
sudo pip3 uninstall tensorflow numpy
途中で「Proceed ? (続行しますか?)」という質問が2回出ますので、キーボードの「y」をタイプしてEnterキーを押してください。

また、TensorFlow 2 系をインストールしていた方は、以下のように keras のバージョンを 2.3.1 に戻す必要もあります。
sudo pip3 install keras==2.3.1 
以上でNumPyは1.15.0から1.12.1に戻り、警告(Warning)は出なくなります。もちろん、TensorFlowもアンインストールされましたので使えなくなります。 ですから、.keras/keras.jsonのbackendの項目を下記のようにtheanoに変更して保存しましょう。
{
    "epsilon": 1e-07,
    "floatx": "float32",
    "image_data_format": "channels_last",
    "backend": "theano"
}

2018年5月15日火曜日

キーボードのテンキーを利用したい場合の注意

OSインストール法のキーボードの設定項目において注意したように、日本語109キーボード上のテンキーを利用したい場合、キーボード上の「NumLock」キーを押してからでないとテンキーとして利用可能になりません。

この件についてもう少し詳しく説明します。

テンキーつきの日本語109キーボードにはNumLockの状態があり、NumLockがONならばテンキーとして動作し、OFFならば矢印キーなどとして動作します。
NumLockの状態は、恐らくキーボード上のLEDの点灯状態で表示されていることが多いでしょう。

WindowsなどではNumLockがONの状態で起動するのに対し、Raspberry PiではNumLockがOFFの状態で起動するようです。

もちろん、手動でNumLockをONにすれば良いのですが、Raspberry Pi起動時にNumLockを自動でONにする方法があるようですので、以下にその方法を記します。
(ただし、システムの設定を変更する必要がありますので、自己責任でお試しください)

まず、以下の2つのコマンドを順に実行し、「numlockx」というアプリケーションをインストールします。
sudo apt-get update
sudo apt-get install numlockx
そして、このnumlockxをRaspberry Pi起動時に実行するようにします。

そのために、設定ファイル/etc/rc.localを管理者権限のテキストエディタで下記コマンドにより開きます。
sudo leafpad /etc/rc.local
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。
sudo mousepad /etc/rc.local
このファイルには様々な設定が書き込まれていますので、それらを壊さないよう注意ながらファイル末尾に移動して下さい。

このファイルの末尾に「exit 0」という行があります。
この行の手前に、「/usr/bin/numlockx on」という1行を追記します。
追記した結果を、元からある「exit 0」とともに表示すると下記のようになるでしょう。
/usr/bin/numlockx on
exit 0
以上の変更を施したら、ファイルを上書き保存し、テキストエディタleafpadを閉じます。 Raspberry Piを再起動し、デフォルトでNumLockが自動的にONになっていたら成功です。

2018年3月14日水曜日

サンプルプログラムの実行にかかる時間

本書では、動作が高速なRaspberry Pi 3やRaspberry Pi 2の利用を推奨し、動作の遅いPi ZeroやPi 1 B+の利用を推奨しませんでした。

本ページでは、実際にどの程度速度に違いがあるのかを表にしてまとめます。

単位は全て秒です。GUIプログラムの場合は「画面が現れて操作可能になるまでの時間」を表しています。

おおむね「Pi ZeroはPi 3 Bの4~5倍程度」、「Pi 1 B+はPi 3 Bの6~7倍程度」の時間がかかるのがご覧いただけるのではないかと思います。

また、Pi 3 B+がPi 3 Bよりも若干高速なこともわかるでしょう。

なお、ディープラーニングの演習のために用いるkeras + theanoは、バージョンアップに応じて計算時間が変わることがあるようです。下記の表では「ml-10」で始まるファイルが該当します。これらのプログラムに対する計算時間は表作成時のものであり、目安とお考えください。

本書のプログラムの実行にかかる時間(単位はすべて秒)
Pi 1 B+ Pi Zero W Pi 2B Pi 3B Pi 3B+ 備考
ml-03-01 13 9 5 2 2
ml-04-01 12 7 3 2 2
ml-04-02 33 22 10 7 6
ml-04-03 35 23 10 7 6
ml-04-04 44 30 14 8 7
ml-04-05 12 8 3 2 2
ml-05-01 112 73 30 17 15
ml-05-01 (itr_max=50000) 5040 3300 590 300 280 長時間の実験(必ずしも実行しなくて良い)
ml-05-02 88 58 23 13 11
ml-05-02 (itr_max=100000) 14400 9000 1260 720 615 長時間の実験(必ずしも実行しなくて良い)
ml-06-01 20 11 4 4 3
ml-06-02 135 86 27 16 14
ml-06-03 47 29 11 7 6
ml-06-04 27 17 5 3 3
ml-06-05 291 188 71 45 41 ランダムなので目安
ml-06-06 22 15 5 3 3
ml-06-07 262 161 74 42 41 ランダムなので目安
ml-06-08 24 15 6 3 3
ml-06-09 225 165 82 44 36 ランダムなので目安
ml-06-10 - - - - - ml-06-08と同等
ml-06-11 - - - - - ml-06-09と同等
ml-07-01 10 7 3 2 2
ml-07-02 11 7 3 2 2
ml-07-03 13 8 3 2 2
ml-07-04 13 8 3 2 2
ml-08-01 7 5 3 3 3
ml-08-02 16 12 4 3 3
ml-08-03 900 300 140 72 83 ランダムなので目安
ml-08-04 17 11 5 3 3
ml-09-01 20 13 5 3 3
ml-09-02 - - - - - ml-09-01と同等
ml-03-01 初回 40 35 13 7 5 kerasインストール後
ml-03-01 二回目 32 25 10 7 5 kerasインストール後
ml-10-01 - - - 490 400 ディープラーニングの学習
(必ずしも実行しなくて良い)
ml-10-02 初回 1580 1007 448 272 200
ml-10-02 二回目 260 172 75 42 35
ml-10-03 - - - 9449 8450 ディープラーニングの学習
(必ずしも実行しなくて良い)
ml-10-04 初回 1709 1168 488 310 230
ml-10-04 二回目 370 245 96 55 49
ml-10-05 - - - - - ml-10-04と同等
ml-10-06 - - - - - ml-10-04と同等
ml-10-07 - - - 24000 20640 ディープラーニングの学習
(必ずしも実行しなくて良い)
ml-10-08 初回 320 232 92 57 43 ml-10-04でCNNの最適化が済んでいるため速い
ml-10-08 二回目 310 225 82 48 42
ml-10-09 - - - - - ml-10-08と同等
ml-10-10 - - - - - ml-10-08と同等


プロキシ(Proxy)環境下での本書の演習の実行

はじめに

職場や学校などでは、ネットワークに接続するためにプロキシ(Proxy)サーバーと呼ばれるものを介する場合が多いと思います。そのような環境下では、本書でネットワーク接続を必要とする演習をそのままでは実行できません。

下記の設定を行えば、全ての演習を実行できるようになりますが、上級者向けの内容ですので、職場や学校のネットワーク管理者など、ネットワークに詳しい方と一緒に作業することをお勧めします。

apt-getコマンド

ソフトウェアのインストールの際に実行するapt-getコマンドを用いるための方法です。

まず、ターミナルソフトウェアLXTerminalを起動し、以下のようにテキストエディタleafpadで設定ファイル/etc/apt/apt.confを作成します。
sudo leafpad /etc/apt/apt.conf
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。
sudo mousepad /etc/apt/apt.conf
このファイルに下記の内容を記述します。「プロキシサーバー名」や「ポート番号」は環境によって異なりますので、ネットワーク管理者にお尋ねください。
Acquire::http::proxy "http://プロキシサーバー名:ポート番号/";
Acquire::https::proxy "https://プロキシサーバー名:ポート番号/";
Acquire::ftp::proxy "ftp://プロキシサーバー名:ポート番号/";
Acquire::socks::proxy "socks://プロキシサーバー名:ポート番号/";
記述が終わったら、ファイルを保存してからleafpadを閉じてかまいません。

以上で、「sudo apt-get update」、「sudo apt-get install (パッケージ名)」などのコマンドが実行できるようになります。

ブラウザなど

次に、ブラウザなどを利用するための方法です。ここでは、Raspbian Stretch用の方法のみ記します。

ターミナルソフトウェアLXTerminalを起動し、以下のように管理者権限のテキストエディタleafpadで設定ファイル/etc/environmentを編集用に開きます。
$ sudo leafpad /etc/environment
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。
$ sudo mousepad /etc/environment
Raspbianのバージョンにもよりますが多くの場合 /etc/environment は何も書かれていない空のファイルですので、そのまま以下の3行を記入してください。「プロキシサーバー名」や「ポート番号」は環境によって異なりますので、ネットワーク管理者にお尋ねください。もし何かが書かれていた場合も、その内容を壊さないように注意しながら、ファイルの末尾に以下の内容を記します。
http_proxy=http://プロキシサーバー名:ポート番号/
https_proxy=http://プロキシサーバー名:ポート番号/
ftp_proxy=http://プロキシサーバー名:ポート番号/
以上の設定を記述したらファイルを保存してleafpadを閉じます。この設定を読み込むためにRaspberry Piを再起動してください。再起動後、ブラウザでインターネット上のウェブサイトを閲覧できるようになっているはずです。

なお、Raspbian Jessie や Wheezy用の方法は、別の書籍用ページである「Raspberry Piで学ぶ電子工作補足情報『プロキシ(Proxy)環境下での本書の演習の実行』」に記しましたので必要に応じて参照してください。

時刻合わせ

プロキシ環境下ではRaspberry Piの時刻合わせが機能しない場合が多いと思います。そのような場合、もし職場や学校内に時刻合わせサーバーが存在すれば、下記の方法で時刻を合わせることができます。

RaspbianのStretchでは、時刻合わせにsystemd-timesyncdが用いられていますので、その設定を行います。ターミナルソフトウェアLXTerminalを起動し、 leafpadで設定ファイル/etc/systemd/timesyncd.confを開きます。
sudo leafpad /etc/systemd/timesyncd.conf
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。
sudo mousepad /etc/systemd/timesyncd.conf
ファイル内で下記のような箇所を見つけます。
(略)
[Time]
#NTP=
#FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3
.debian.pool.ntp.org
このうち、NTPに関する行の先頭の「#」を削除し、「=」の右辺にお使いの時刻合わせサーバーを記述します。 時刻合わせサーバが存在するかどうかはネットワーク管理者にお尋ねください。
記述後、ファイルを保存してからleafpadを閉じます。そして、Raspberry Piを再起動すれば時刻が合うようになります。

なお、時刻合わせサーバーを用いず、手動で時刻を設定したい場合、ターミナルでコマンドを実行して時刻を合わせます。例えば、3月14日23:09に合わせたい場合は下記のようなコマンドを実行します。
sudo date 03142309


10章のpipコマンド

10章では、kerasとtheanoのインストールにpipコマンドを用いました。プロキシ環境下でpipコマンドを使う場合、下記のようにコマンドを読み替えてください。もちろん、「プロキシサーバー名:ポート番号」の部分は環境に応じて読み替える必要がありますので、ネットワーク管理者にお尋ねください。
sudo pip --proxy=http://プロキシサーバー名:ポート番号 install keras theano