どうでも良いことですが、私の大学(院)時代の専門は機械学習やパターン認識の近接領域です。
当時は侵入検知や一般物体認識など、一部の限られた研究者のあいだで非線形手法が流行していたところに、古臭くて見向きもされていなかったニューラルネットが圧倒的な性能を見せつけ、シンギュラリティという言葉が生まれて一躍、大ブームが巻き起こりました。
流行の波に乗って、多くの人が新たに機械学習ライブラリに触れてみる機会が多くなった一方で、個人的には徐々に機械学習から距離を置いていきました。
それは、数十台のサーバコンピュータを数日連続して動かし続けたり、国内に数えるほどしかない大型計算機システム(つまりはスパコン)の利用申請をしたり、要するに計算資源だよりの力技でゴリ押しする風潮に魅力を感じなかったわけです。
特定の環境に依存しすぎていて、少しでも条件が変わったときにプロジェクトの再現や継続が難しいのはどうなのかなと。
Raspberry Pi(ラズパイ)は、ある意味、その対局にあります。
スマートフォンよりも小さく物理的に持ち運ぶことも容易、処理性能は玩具かせいぜいが低価格PCと比較できるくらい、学習データは外付け HDD に頼ればいいとして、それを取り込んでモデルを構築する際にメモリに載せられるかどうかというスペックです。
Contents
Raspberry Pi で行う意義
正直、それほど古くないノートPCをお持ちなら、それに Linux をインストールしたほうがより快適な機械学習環境を構築できるはずです。
敢えて非力な Raspberry Pi で計算負荷の高い行列計算や確率計算をやろうとするなんて玄人好みだなと思っていましたが、最近、すこし考えをあらためました。
単純ベイズなどの例外を除いて、機械学習のモデル構築やクラスタリングは CPU や GPU、メモリなどを食い潰す勢いで消費しながら数時間から数日間に及ぶ処理を実行します。
例えば、『吾輩は猫である』(347,704字)を訓練データにして一般的なニューラルネットワークで 140 字のマイクロブログ・テキストを生成しようとした場合、10GB以上のメモリを使用して10時間以上の処理時間が掛かります。
たとえ処理性能に自信のあるハイエンド・ゲーミングPCをお持ちだったとしても、バックグラウンドで常時こんな処理が動いていては、もはや快適な環境とは言えません。
平気で数十秒間フリーズします。
ここで「機械学習はメインPCでやるべきではない」と開き直れると Raspberry Pi の可能性が見えてきます。
価格やスペース的にもノートPCより気軽に購入できますし、ほかの処理を行わないのであればディスプレイもスピーカーも必要ありません。
処理能力の低さは実行時間を増やすことでカバーするほかにありませんが、どうせハイスペックなデスクトップPCを使用しても長時間掛かることは避けられない問題です。メインPCのリソースを占有されるよりも Raspberry Pi に処理を任せて放置していたほうが気楽という発想の転換です。
もちろん Raspberry Pi では実現できないこともあります。後述するように Raspberry Pi の CPU や OS はやや特殊なので、一部のライブラリやフレームワークは使用できません。
また処理能力が非力でメモリ容量も乏しいため、通常のPCに比べて実現できることも限られます。それでも株価などの時系列データの分析を行ったり、訓練されたモデルを用いてリアルタイムで画像認識を行うことぐらいは十分にできます。
前述のように業務や研究とは異なり、個人が遊びで動かすぐらいの用途であれば、それほど問題になることはないかと思われます。
どのモデルを選ぶべきか
これは簡単で、入手時点でもっともメモリ容量の大きな最新のモデルです。
機械学習はいかに質の良い訓練データを大量に準備して、それを限られたメモリに載せられるかという点にほぼ全てが掛かっているので、メモリ容量が少ないとできることが限定されます。
ちなみに、ほかの要素はパラメータ調整という素人には真似できない職人芸なので、ご自身で偏微分したくなったりしない限りは下手にプリセットを変更しないほうが良いです。
モデル一覧は公式サイトから確認できます。
Buy a Raspberry Pi – Raspberry Pi
https://www.raspberrypi.com/products/
2022年1月現在では Raspberry Pi 4 Model B (8GB) 一択です。
ラズベリーパイ 4 コンピューターモデルB 8GB Raspberry Pi 4 ラズパイ 4 TELEC認定取得済み (Raspberry Pi 4 8GB)
Zero 系統や Pico 系統は (1) メモリ容量が少ないこと、 (2) USB Type-Aポートを備えていないことから機械学習用途にはあまり向いていません。
これらは我が家ではサーバからバックアップデータを取得してきたり、各所のセンサデータを記録するロガー、または NAS (SAMBA) として活躍ていますが、機械学習に使おうとは思わないですね。
リアルタイム画像分類用の安価な USB ウェブカメラや 100GB 単位の訓練データを保存しておく外付けハードディスクとアダプタなしに接続できないですし。
セットアップ
いざ Raspberry Pi を購入し、OSをインストールして、最初に気をつけるべきことは CPU です。
最近のハイエンド PC は 64 ビットのものが多いのに対して Raspberry Pi は 32 ビットが普通に使われています。
いつものPCと同じ感覚でライブラリをインストールされると動作しない可能性があります。
CPU情報
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ lscpu Architecture: armv7l Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 Vendor ID: ARM Model: 3 Model name: Cortex-A72 Stepping: r0p3 CPU max MHz: 1500.0000 CPU min MHz: 600.0000 BogoMIPS: 126.00 Flags: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 $ cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 270.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 Hardware : BCM2711 Revision : c03112 Serial : 0000000000000000 Model : Raspberry Pi 4 Model B Rev 1.2 |
OS情報
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 10 (buster)" NAME="Raspbian GNU/Linux" VERSION_ID="10" VERSION="10 (buster)" VERSION_CODENAME=buster ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs" $ gcc --version gcc (Raspbian 8.3.0-6+rpi1) 8.3.0 |
基本設定
まずは基本設定です。パッケージを更新して、ビルドツールを導入して、デフォルトで使用する Python を Python3 に変更します。
1 2 3 4 5 6 7 8 9 10 11 |
$ sudo apt update -y $ sudo apt upgrade -y $ sudo apt install build-essential -y $ python --version Python 2.7.16 $ cd /usr/bin/ && sudo unlink python && sudo ln -s `which python3` python $ python --version Python 3.7.3 |
MiniConda
つぎにデータ分析便利セットこと Anaconda を導入したいところなのですが、 Raspberry Pi の限られた記憶領域(というか SD カード)にインストールするには Anaconda のファイルサイズはやや大き過ぎるので、その縮小版パッケージの MiniConda をインストールします。
1 2 3 4 5 |
$ wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-armv7l.sh $ /bin/bash Miniconda3-latest-Linux-armv7l.sh $ echo export PATH="/home/pi/miniconda3/bin:$PATH" >> ~/.bashrc $ conda --version conda 3.16.0 |
縮小版と言えど、これだけあれば大体のことが可能になります。
TensorFlow
最後は定番の TensorFlow です。Raspberry Pi で動作するのは訓練済みの TensorFlow モデルを実行するためのフレームワークである TensorFlow Lite です。
こちらは基本的にはモデル構築には用いることができませんが、更新頻度が高く、流動的なのでご閲覧時点では機能が変更されているかもしれません。
ドキュメントの指示に従ってインストールできれば話がはやいのですが tensorflow/lite/tools/make/download_dependencies.sh は2021年8月以降は非推奨になっていて使用できません。
どうも Raspberry Pi の非力な CPU やメモリを用いてのコンパイルは忌避されている感があり、公式ページに示されている Docker コンテナを用いたデスクトップやサーバ環境でのクロスコンパイルのほうが簡単です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$ docker pull tensorflow/tensorflow:devel $ docker run -it -p 8081:8888 tensorflow/tensorflow:devel # ldd --version ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31 # apt install cmake # cd tensorflow_src/ # curl -LO https://storage.googleapis.com/mirror.tensorflow.org/developer.arm.com/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz mkdir -p ${PWD}/toolchains tar xvf gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz -C ${PWD}/toolchains # ARMCC_PREFIX=${PWD}/toolchains/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu- ARMCC_FLAGS="-funsafe-math-optimizations" cmake -DCMAKE_C_COMPILER=${ARMCC_PREFIX}gcc \ -DCMAKE_CXX_COMPILER=${ARMCC_PREFIX}g++ \ -DCMAKE_C_FLAGS="${ARMCC_FLAGS}" \ -DCMAKE_CXX_FLAGS="${ARMCC_FLAGS}" \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_SYSTEM_PROCESSOR=aarch64 \ ./tensorflow/lite/ -- Configuring done -- Generating done -- Build files have been written to: /tensorflow_src |
RNN実行例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
top - 11:16:44 up 11:11, 1 user, load average: 1.87, 3.84, 5.92 Tasks: 526 total, 1 running, 522 sleeping, 0 stopped, 3 zombie %Cpu(s): 0.7 us, 2.9 sy, 0.0 ni, 93.5 id, 2.9 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 32046.1 total, 257.2 free, 31404.7 used, 384.2 buff/cache MiB Swap: 30517.0 total, 12057.9 free, 18459.1 used. 206.9 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3568 goddard+ 20 0 4566592 102456 43600 D 17.6 0.3 3:58.00 gnome-shell 174 root 20 0 0 0 0 S 11.8 0.0 44:59.00 kswapd0 29429 goddard+ 20 0 59.2g 29.0g 0 D 11.8 92.8 2126:13 python 18 root 20 0 0 0 0 S 5.9 0.0 0:05.73 ksoftirqd/1 3676 goddard+ 20 0 315556 1908 1220 S 5.9 0.0 0:00.15 gvfsd-trash 729002 root 20 0 2231940 0 0 S 5.9 0.0 1:38.44 dockerd |
1 2 3 4 5 6 7 8 9 10 |
$ python Python 3.7.0 (default, Jun 28 2018, 13:15:42) [GCC 7.2.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> import tensorflow as tf >>> print(tf.__version__) 2.7.0 >>> print("Num GPUs Available: ", len(tf.config.experimental.list_physical_devices('GPU'))) 2021-12-04 11:18:55.058744: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:939] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero Num GPUs Available: 1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$ nvidia-smi Sun Dec 4 12:04:17 2021 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 495.29.05 Driver Version: 495.29.05 CUDA Version: 11.5 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 NVIDIA GeForce ... On | 00000000:0B:00.0 On | N/A | | 25% 40C P8 11W / 250W | 354MiB / 11175MiB | 19% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | 0 N/A N/A 1805 G /usr/lib/xorg/Xorg 35MiB | | 0 N/A N/A 3454 G /usr/lib/xorg/Xorg 139MiB | | 0 N/A N/A 3568 G /usr/bin/gnome-shell 39MiB | | 0 N/A N/A 939494 G ...gAAAAAAAAA --shared-files 12MiB | | 0 N/A N/A 1009673 G ...AAAAAAAAA= --shared-files 114MiB | +-----------------------------------------------------------------------------+ |