【機械学習】単眼カメラ×多項式回帰で距離推定＋知識蒸留の工夫まとめ


## 概要
　私はNoa.hというチームにプログラマーとして所属しており、RCJ(RoboCup Junior)というロボットサッカーの大会に出場しています。今回開発した単眼カメラによる距離測定はこの大会で使用する機体に搭載し機体からのボールやゴールの距離を求めるのに使用しました。

 ![スクリーンショット 2025-05-12 233844.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921462/75c68edd-86e5-4936-bf25-208eea2de178.png)

 
 大会規定や高い処理速度が求められる試合への対応のため、条件は以下のようになります。
 
#### 使えるもの
- 角度高さが固定された単眼カメラ - UnitV
- ささやかな計算資源 - Teensy4.1
#### 使えないもの
- ステレオカメラ
- Depthセンサー付きのカメラによる深度測定
- 画像処理による深度測定


jetson積めば何とかなるものが多いですがうちにそんなお金はありません。仕方がないのでカメラから得られる対象のx,y座標の情報のみで機械学習を行うことにしました。

## 事前実験
今回はTeensy4.1上での実装とRCJの試合での運用が目標なので、ある程度軽量なモデルにすることが必須になっています。事前実験では多項式回帰がそれなりにいいスコアになったのでこれを使用します。またx,yを特徴量にしたモデルよりも検出した物体の角度と物体の下辺のy座標を特徴量にしたモデルの方が格段に精度がよかったのでこれを採用します。以下theta,under_yとする。


## データ集め
theta,under_yと距離の対応したデータを集めます。0~80cmの区間で166個のサンプルを集めました。


## 手法① 多項式回帰モデル
今回使用するささやかな計算資源ことTeensyさんはGPU等に比べるとはるかに劣りますが、マイコンの中ではかなり処理も早く多項式回帰モデル程度であれば容易に動かすことができます。
```
最良モデル（5次）を保存します...
MAE:0.94 
RMSE:1.29
```
MAE(平均絶対値誤差)は0.94とかなり精度の高いモデルができました。
記事には書いていませんが特徴量が決まるまではMAEが3を切っただけで歓喜していたので正直もう十分な気もします。まさか特徴量の選定だけでここまで精度が上がるとは思っておらず、精度を向上させるために大型モデルからの蒸留をするという案を考えていたのですがもう必要ないかもしれませんね。でもせっかくなので試してみましょう。


## 手法② 蒸留モデルの作成
LLM界隈でよく耳にする手法の一つに「知識蒸留（Knowledge Distillation）」があります。これは大型の複雑なモデルを先に作成し、その出力を用いて学習データを水増し軽量なモデルを学習することで大型モデルの性能を小型モデルにも継承させるというような手法です。この蒸留モデルは少ない計算資源で運用できながら性能としては大きいモデルとほぼ同位のものを再現できます。この手法を利用し大型のニューラルネットワーク（多層パーセプトロン）を利用したモデルを作成し、このモデルの出力結果をデータに多項式回帰を学習し精度向上を目指します。

### 蒸留元の大型モデル[128,256,128]
```
MAE: 0.7747 
RMSE: 1.1607
```
学習に使用したデータは手法①の多項式回帰と同じものになっています。
ほんのわずかではありますが多項式回帰モデルよりも高い精度を出すことができました。
続いてこのモデルから161*121ピクセルすべてに対して距離推定を行い蒸留モデル向けの学習データを作成します。今回は80cmまでしか検証できるデータがないので0~80までのデータだけを使用します。

![NN126256128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921462/bae979bf-41b2-4360-8e1e-efd1e3421398.png)

学習用データ(実測値)を捉えられていることが確認できました。


### 知識蒸留された多項式回帰モデル[10次]
```
 MAE: 0.96
 RMSE: 1.65
```
意外なことに実測値のデータからのみ学習した多項式回帰モデルよりも性能が下がってしまいました。原因としてNNモデルと多項式回帰モデルの間で柔軟性が急速に失われたことが考えられます。LLM関連の論文で蒸留を行う際にモデルを一気に小さくするよりも間に中間のサイズのモデルを挟んだ方が性能の劣化が起こりにくいというような内容のものを見かけたことを思い出したので、中間サイズのモデルを経由させて蒸留モデルを作り直してみることにしました。

### 二段階の知識蒸留

#### 中間サイズのNNモデル[96,96]
```
MAE:0.8960
RMSE:1.4537
```

性能としてはNNモデル[128,256,128]以下で多項式回帰モデル(蒸留なし)よりはいいものとなったので今のところ順調ですね。さっきと同様にこのモデルから水増しした学習データを作ります。

![distral-9696.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921462/5ea1dbad-6776-4f37-8a2f-b247f7c982f6.png)

#### 二段階目の蒸留多項式回帰モデル[12次]
```
MAE: 0.83,
RMSE: 1.49
```
直接の蒸留や蒸留なしの多項式回帰モデルよりも高い性能のモデルの作成に成功しました。
蒸留で性能向上はできましたが、結局次数が上がってしまっていることも考えると少し複雑な気持ちです。
二段階の知識蒸留の際にMAEが中間モデルよりも二段計目の多項式回帰モデルの方が小さかったのは、複雑性が失われたことによるノイズの軽減ではないかと考えられます。

![distral-2tier-12degree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921462/d78881a6-25af-4a6f-955d-e2562d546d34.png)

## まとめ
単眼カメラから得られるunder_y,thetaだけの情報から距離推定は、ひとまず80cmまではある程度の精度が確認できました。またモデルの性能向上のための知識蒸留は段階を踏んで行うことで通常の学習よりも精度を上げられることがわかりました。しかしどの方法をとった場合もそこまで大きな差は出ず、一番の性能向上要因はちゃんとデータを取って置かなかったせいで書けなかった特徴量の選定でした。

## 展望
ここまで書いておいてなんですが、精度向上についてはデータの偶然の偏りが影響してしまっている可能性も否めません。以下のグラフのように距離が70cmを超えているデータを除くと精度が向上するということも追加の検証でわかったので、全く使用していないデータを集めて再度検証するなどより詳細なモデルの性能検証が必要だと考えます。
また80cm以上遠くの物体に対しての距離推定能力についても今後検証したいです。

![de-ta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921462/8888091f-d43e-407b-aa19-d18f17584581.png)


## Teensyへの実装
これに関してはチームメンバーに丸投げしているので、メンバーが記事を書き次第リンクを張る予定です。今言及できることとしては問題なくロボットサッカーの試合に投入できるレベルの速度でのｋ推定には成功しています。

## 最後に
この距離推定方法はLLM界隈が好きでたまたま勉強として機械学習に触れていたのがきっかけで思いついたものでした。ロボット方面とは完全に別のものとして勉強していたつもりでしたが、結果ロボット開発にも活きるものとなったことにはどこか感慨深さがありました。おかしな方向に伸ばしたスキルツリーが運よく噛みあう瞬間が人生で一番気持ちいと思っているのでこれからもいろいろ勉強したいと改めて思いました。