Raspberry Pi で機械学習

どうでも良いことですが、私の大学(院)時代の専門は機械学習やパターン認識の近接領域です。

当時は侵入検知や一般物体認識など、一部の限られた研究者のあいだで非線形手法が流行していたところに、古臭くて見向きもされていなかったニューラルネットが圧倒的な性能を見せつけ、シンギュラリティという言葉が生まれて一躍、大ブームが巻き起こりました。

流行の波に乗って、多くの人が新たに機械学習ライブラリに触れてみる機会が多くなった一方で、個人的には徐々に機械学習から距離を置いていきました。

それは、数十台のサーバコンピュータを数日連続して動かし続けたり、国内に数えるほどしかない大型計算機システム(つまりはスパコン)の利用申請をしたり、要するに計算資源だよりの力技でゴリ押しする風潮に魅力を感じなかったわけです。

特定の環境に依存しすぎていて、少しでも条件が変わったときにプロジェクトの再現や継続が難しいのはどうなのかなと。

Raspberry Pi(ラズパイ)は、ある意味、その対局にあります。

スマートフォンよりも小さく物理的に持ち運ぶことも容易、処理性能は玩具かせいぜいが低価格PCと比較できるくらい、学習データは外付け HDD に頼ればいいとして、それを取り込んでモデルを構築する際にメモリに載せられるかどうかというスペックです。

[toc]




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情報
 $ 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情報
 $ 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 に変更します。

$ 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 をインストールします。

$ 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 コンテナを用いたデスクトップやサーバ環境でのクロスコンパイルのほうが簡単です。

$ 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実行例

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
$ 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
$ 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 |
+-----------------------------------------------------------------------------+

Leave a Reply

Your email address will not be published. Required fields are marked *