工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

ベビーリーフを育てる(2) --- まとめ ---

概要

ビーリーフの栽培を一旦終了するので、ここまでのまとめをする。



背景と目的

ビーリーフの栽培を始めてから、約3か月が経った。次の作物の栽培を始めるのでいったん栽培を終了しなければならないのと、発芽以降の記録をさぼっていたので、ここまでのまとめを書き記す。



詳細

1. まとめ動画

以下にまとめた。朝7:30頃に撮影しているが、冬場で明るくなるのが遅いせいか、夏場よりだいぶ画質が悪い。


www.youtube.com


2. 種まきから発芽まで

  • 発芽までの日数
    • 動画を見る限り、2021/11/07に種まきしてから6日で発芽したようだ。種の説明書などを見ると5日程度とあったので、まずまず説明書通り。いつもそうだが、発芽するまではドキドキ。
  • 発芽率
    • 種を全体にバラバラ巻いたので数値を出すことはできないが、その後の成長具合を見ると全体的にそれなりに芽が出てきてくれているので、発芽率は悪くないと思われる。


3. 収穫まで

  • 動画を見る限り、発芽から1か月でそこそこ大きい葉が育って食べられるくらいにはなっているが、2021/12/21に葉の量が減っているので収穫していると思われる。結局発芽から初収穫まで1か月以上かかったのかも?でも、それよりも前に収穫したような気がする。自分で育てたのに全然覚えていない。動画を見てもわからなかった。


4. 収穫以降

  • 初収穫以降、本格的に寒い時期に入り、あまり成長は速くないが、順調に育ってくれた。1週間に1回くらいは収穫しただろうか。1回の収穫量は片手いっぱいになるくらいなので、サラダの足しくらいにしかならなかったが、味は良好。


5. 感想

  • ベランダの日当たりがいまいちなせいもあり、冬場の午前中は特に日照時間が少ない。
  • 全体の収穫量が少ない。寒さで育ちが遅いせいもあるかもしれないが、絶対量としてプランター1個では少ないのだろう。もう1つくらい用意してもいいのかも。
  • 収穫量は少なかったが、味はいいので、また育てたい。



まとめと今後の課題

ビーリーフの栽培ができた。結構おいしかったので、次の機会があればぜひ育てたい。


M5STACKのUnit CAMにArduinoのプログラム書き込む

概要

M5STACKのUnit CAMに配線を施し、Arduinoのプログラム書き込んでみた。



背景と目的

以前、以下の記事で、OV2640というカメラ基板とESP32を接続したものを作成した。

dekuo-03.hatenablog.jp

そして、また同様のものが欲しくなったのだが、同じものを作ると手間がかかる。しかし、Amazonで相変わらず大量に出回っている技適の通っていない怪しい格安基板に手を出すわけにもいかないので、何かいいものがないか探していたところ、 M5STACKのUnit CAM というものをスイッチサイエンスで見つけた。1000円ちょっとと非常に手ごろなので、これを買って動かしてみることにした。

※先に結論を書くと、

当然ながら、ちゃんと動く。ただし、UXGAは撮れない。商品が悪いわけではなく、PSRAMがないことを見落とした自分が悪い。

OV2640が載っており最大解像度2MPixelという文言を見て、てっきりPSRAMが載っているものと思っていたが載っていない。すなわち、この記事で書いた通り、UXGAでは撮れなかった。同じ轍を2回踏むという、ひどいミスをしてしまった。とはいえ、まあSXGAくらいでは撮れるし、いずれ活躍の機会がないとは言えないのでひとまず動作の記録を残して、部品箱に眠らせておくことにした。



詳細

1. 配線

Unit CAMは、本来Grove端子で接続してM5STACK関連のデバイスとつないで遊ぶ想定のものなので、ファームウェア書き込みも専用シリアルライターを使う想定。しかし、私の手元にあるのは、これなので、同じ接続ができない。これについてもロクに考えずに買ってしまったせいで、面倒な配線作業が発生した。以下のように、これを参考に、けっこういろいろ配線した。

  • R1からTXD0に斜めに伸びる1kΩは、ESP32でプログラム書き込みに失敗したときの解決方法に倣ったプルアップ抵抗。これって、書き込めない症状は確かに改善するものの、最近自分のライターがおかしいだけ???のような気もしてきた。あまり自信がない。でも、今回もこの1kΩがないと書き込めなかったのは確か。
  • 3.3V, EN, IO0は写真の外側にESP32が書き込みモードに入るためのタクトスイッチを設けて接続している
  • 3.3V、SY8089AAACというレギュレータの3.3V出力に繋がるR1から取り出す

f:id:dekuo-03:20220206175841j:plain


2. Arduinoプログラム書き込み

プログラムは、arduino-esp32のサンプルプログラムにあるCameraWebServerとする。変更点は、ここを参考にピン接続のGPIO番号だけ定義する。

2022/03/27追記 arduino-esp32の最新バージョンは2.0.2だが、本記事はv1.0.6のCameraWebServerサンプルを基にして作成する必要があることがわかった。v2.0.2だと必要なファイルがインクルードできず、コンパイルできない。

// ピン設定
#define Y2_GPIO_NUM 32
#define Y3_GPIO_NUM 35
#define Y4_GPIO_NUM 34
#define Y5_GPIO_NUM 5
#define Y6_GPIO_NUM 39
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 36
#define Y9_GPIO_NUM 19
#define XCLK_GPIO_NUM 27 // XCLK
#define PCLK_GPIO_NUM 21 // PCLK
#define VSYNC_GPIO_NUM 22 // VSYNC
#define HREF_GPIO_NUM 26 // HREF
#define SIOD_GPIO_NUM 25 // SIOD
#define SIOC_GPIO_NUM 23 // SIOC
#define PWDN_GPIO_NUM -1 // 接続なし
#define RESET_GPIO_NUM 15 // RESET

そして、

// Select camera model
#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
:

#include "camera_pins.h"

の部分は、参照しないので削除する。

3. 動作確認

Webブラウザで、所定のアドレスにアクセスしたところ、ちゃんと表示された。撮れた画像は以下。SXGAである。UXGAも被写体によっては撮れるが、複雑な絵柄だと、エンコードされたjpegバイナリのサイズも大きいのでRAMに入りきらず撮れない。実質的にSXGAくらいが最大だろう。まあ、悲しいが想定通りの動き。

f:id:dekuo-03:20220206180437j:plain



まとめと今後の課題

Unit CAMにArduinoプログラムを入れて動かすことができた。買ったもの自体は失敗なのだが、まあ後々メモとして役立てばよい。


天気図画像データから、24時間以内の降雨の有無を予測する

概要

天気図画像データから、24時間以内の降雨の有無を予測してみた。



背景と目的

ある事情で、ディープラーニングを使ったモデルを作成する必要が出た。テーマは、データが集めやすそうな天気関連のものとして、記事タイトルにある内容で行うこととした。画像データから降雨に関わる重要な特徴を学習してうまく予測するモデルが作れるか試す。



詳細

1. 実施内容

予測対象地点は、さいたま市とした。


2. データの収集

  • 天気図データは、tenki.jpの過去の天気図データを用いる。2021年1月1日~2021年12月20日までの約1年分とする。Webスクレイピング等により収集した。3時間ごとに1枚の天気図がある。(ただし、0時はない)
https://tenki.jp/guide/chart/
  • 予測対象の降雨の有無は、さいたま市の過去のデータを以下の気象庁Webサイトからダウンロードした。
https://www.data.jma.go.jp/obd/stats/etrn/index.php


3. データセットの作成

3.1 天気図データ

今回使用する天気図データは、

  • 太平洋やロシアなど広範囲をカバーする
  • 地形や緯線、経線も含まれている

となっているが、

  • 一般的に、予測対象地点から大きく離れる場所や東側の大部分はあまり予測に重要でなさそうである
  • 同じ画角で切り出したとすると、予測対象地点は常に画像中の同じ位置だから、画像中の地形や緯線や経線は予測と無関係であり、天気図記号の位置関係のみが予測に関係する

と考えられた。そこで、

  • すべての画像から平均画像を作成し、各画像から減算して地形や緯度経度の線地形を消去
  • 予測対象地点がおおむね中心となるように日本付近を160 * 160pixelで切り出す
  • RGBチャンネルを分解してコントラストなどを調整
    • 青は寒冷前線マークの検出
    • 緑は天気図記号抽出がしにくいため不使用
    • 赤は等圧線、高気圧/低気圧マーク、温暖前線の検出
  • 青チャンネルと赤チャンネルを加算
  • 計算量削減のため天気図記号が認識可能な程度の80 * 80pixelに圧縮

といった方法で、画像を約2500枚作成した。すなわち、80pixel * 80pixel * 1channelのcreatedチャンネルが最終的に使用される画像である。なお、さらっと書いているが、実は天気図記号を消さずに地形や緯度経度の線を消すには結構試行錯誤した。データセット作成で苦労するのはよくある話だが。

f:id:dekuo-03:20220117233701p:plain

参考: 平均画像

f:id:dekuo-03:20220117231659j:plain


3.2 降雨データ

降雨データは、天気図の時刻を起点に、24時間以内の合計降雨量が1mmでもあれば降雨あり、0mmなら降雨なしとして、2次元ワンホットベクトル化した。データ全体における降雨なし/降雨ありの比率はおよそ68%である。


4. モデルの作成

畳み込み層と全結合層を組み合わせたニューラルネットワークとした。実装は、tensorflowを用いた。 層の深さ、チャンネル数、フィルタサイズ、正則化パラメータ等は、かなり試行錯誤して決めた。フィルタサイズやプーリングの有無は、天気図記号のピクセル数等を考慮した結果である。正則化は強すぎると学習しないし、弱ければ意味がない。

input = Input(shape=(H, W, 1), name="sma_input1")

x = Conv2D(64, 5, padding="same", activation="relu")(input)

x = MaxPooling2D()(x)

x = Conv2D(192, 3, padding="same", activation="relu", kernel_regularizer=regularizers.l2(0.005))(x)

x = MaxPooling2D()(x)

x = Conv2D(192, 3, padding="same", activation="relu", kernel_regularizer=regularizers.l2(0.005))(x)

x = MaxPooling2D(pool_size=(5, 5))(x)

x = Flatten()(x)

x = Dropout(rate=0.5)(x)

output = Dense(128, activation="softmax")(x)

x = Dropout(rate=0.5)(x)

output = Dense(2, activation="softmax")(x)

model = Model(inputs=input, outputs=output)

model.compile(
    loss="categorical_crossentropy", 
    optimizer='Adam',
    metrics=["accuracy"]
)

model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
sma_input1 (InputLayer)      [(None, 80, 80, 1)]       0         
_________________________________________________________________
conv2d_9 (Conv2D)            (None, 80, 80, 64)        1664      
_________________________________________________________________
max_pooling2d_9 (MaxPooling2 (None, 40, 40, 64)        0         
_________________________________________________________________
conv2d_10 (Conv2D)           (None, 40, 40, 192)       110784    
_________________________________________________________________
max_pooling2d_10 (MaxPooling (None, 20, 20, 192)       0         
_________________________________________________________________
conv2d_11 (Conv2D)           (None, 20, 20, 192)       331968    
_________________________________________________________________
max_pooling2d_11 (MaxPooling (None, 4, 4, 192)         0         
_________________________________________________________________
flatten_3 (Flatten)          (None, 3072)              0         
_________________________________________________________________
dropout_6 (Dropout)          (None, 3072)              0         
_________________________________________________________________
dropout_7 (Dropout)          (None, 3072)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 2)                 6146
=================================================================
Total params: 450,562
Trainable params: 450,562
Non-trainable params: 0
_________________________________________________________________


5. 学習と評価

5.1 学習

  • ホールドアウト法で学習/検証/テストを行う
    • データセット全体の順序をシャッフル
    • 全体を0.75:0.25に分割し、学習/検証用とテスト用とした
    • 学習/検証用を0.75:0.25に分割し、学習用と検証用とした
  • バッチサイズは128
  • エポック数は60

以下が、60エポック完了後の損失と精度。精度は80%台前半。40-50エポックあたりで、検証データに対するロスが下がらなくなっているので、60エポックは少しやりすぎ。

f:id:dekuo-03:20220117233648p:plain


5.2 テストデータによる評価

検証精度とほぼ同様の81%となった。


6. 考察と改善案

6.1 考察

精度は80%台前半で、データ全体における降雨なし/降雨ありの比率はおよそ68%なので、このモデルは天気図から降雨に関連する何らかの特徴をある程度認識できていると考えられる。


6.2 改善案

今回使用したものは、基本的なCNNを使ったネットワーク構成なので、より発展的なネットワーク要素を取り入れることで、精度の向上が図れるのではないかと考える。また、入力がある時点の1枚の画像であるが、天気は時間経過とともに変化することを考えると、時系列性を考慮することも有効と考えられる。具体的には、

  • (案1)ResNetやDenseNetのような残差接続を導入する
  • (案2)時間的に並んだ3枚の天気図をまとめ、3チャンネルの入力データとする

などがある。時間があったらやってみたい。



まとめと今後の課題

天気図画像データから、24時間以内の降雨の有無を予測することにトライしてみた。