Pythonによるデータ分析・機械学習ブログ

Pythonによるデータの前処理・グラフ化、機械学習、統計解析、画像処理、Webスクレイピング、自然言語処理の基礎について紹介していきます。

MENU

【第19回】YOLOv9で自作データセットを用いて学習

はじめに

 近年、AI(Artificial Intelligence:人工知能)の急速な発展に伴い、それらを用いた技術が活用され始めています。例えば、AIによる画像認識技術として物体検出などがあります。物体検出は「画像の中から特定の物体の位置、種類、個数などの情報を認識する技術」であり、AIを用いて比較的高速に画像内の物体情報を取得することができます。この技術を用いて製造業では品質評価、外観検査、異常検知などに活用されています。

 リアルタイムに物体検出を行うアルゴリズムにYOLO(You Only Look Onse)と呼ばれるものがあり、CNN(Convolutional Neural Network:畳み込みニューラルネットワーク)を用いたアルゴリズムとなっています。2024年2月に最新の物体検出モデルYOLOv9が公開されています。

 本記事では、YOLOv9で自作データセットを用いて学習を行う方法を簡単に紹介します。

推論デモについての内容は下記の記事をご覧ください。

chantastu.hatenablog.com

 

1. YOLOv9のリポジトリ

YOLOv9のGithubリポジトリは以下です。

github.com

 

2. 動作環境構築

以下のコマンドで動作環境を構築できます。

 

3. データセットの用意

Roboflowで学習のテストを実施するためのサンプルデータセットを用意しました。アノテーション内容としては画像20枚に対してpersonとpotted plantの2クラスに対して矩形付与をしており、学習:検証:テスト=7:2:1の割合になっています。下記がアノテーション画像例です。

 

下記リンクからZipファイルがダウンロードできます。

https://app.roboflow.com/ds/Cmu0SZTXY7?key=VwBP4N8NgZ

また、以下のコマンドでディレクトリにダウンロードできます。

次にダウンロードした中のdata.yamlファイルの一部を修正します。

data.yamlを開くと、下記のようにtrain、valid、testのパスが書かれた行があるかと思います。

この部分のパスを修正します。上記でデータセットを「datasets/detect-test」内にダウンロードしたので、その部分を反映させます。以下のように内容を修正します。

 

4. 事前学習済みモデルの取得

 次に推論で使用するYOLOv9で提供されている事前学習済みモデル「gelan-c.pt」をダウンロードします。今回はyolov9ディレクトリ直下にweightsフォルダを作成し、そこにモデルをダウンロードします。

 

5. 学習実行

 それでは学習を実行していきます。下記のコマンドを実行することで学習が実行されます。--batchはバッチ数、--epochはエポック数を指定できるので適宜変更してください。

実行すると下記のようなログが表示されます。最後の方を見ると「runs/train/exp8/weights/best.pt」のパスに学習時の精度が良かったモデルが保存されていることが確認できます。

 

6. 検証

次にバリデーションをしていきます。ここでは学習したモデルの品質を評価します。下記のコマンドで実行します。--batchはバッチ数、--confは信頼度スコアの閾値、--iouはNMSの閾値を指定できるので適宜変更してください。

--dataは先ほど修正したdata.yaml相対パスを、--weightsは学習したモデルが格納された相対パスを指定します。

上記プログラムを実行すると下記内容が表示されます。

 

7. カスタムモデルで推論

最後にカスタムモデルで推論をしていきます。下記のコマンドで推論を実行します。ここで--confは信頼度スコア、--weightsには学習したモデルの相対パス、--sourceにはテスト画像が格納されたディレクト相対パスやテスト画像の相対パスを指定します。

推論実行後、「/runs/detect/exp{No.}※No.は任意の数字」に推論結果の画像が保存されます。今回の結果は下図のようになります。

 

オススメ書籍

物体・画像認識と時系列データ処理入門

現場で使える!PyTorch開発入門 深層学習モデルの作成とアプリケーションへの実装

PyTorchで作る!深層学習モデル・AIアプリ開発入門

 

おわりに

 本記事では、YOLOv9で自作データセットを用いて学習を行う方法を簡単に紹介しました。最新のYOLOv9は非常に使いやすい印象です。アノテーション・学習をご自身でも行ってみて、目的達成のために物体検出を活用してみてください。

 

【第18回】YOLOv9による物体検出:動作環境の構築と推論デモ

はじめに 

 近年、AI(Artificial Intelligence:人工知能)の急速な発展に伴い、それらを用いた技術が活用され始めています。例えば、AIによる画像認識技術として物体検出などがあります。物体検出は「画像の中から特定の物体の位置、種類、個数などの情報を認識する技術」であり、AIを用いて比較的高速に画像内の物体情報を取得することができます。この技術を用いて製造業では品質評価、外観検査、異常検知などに活用されています。

 リアルタイムに物体検出を行うアルゴリズムにYOLO(You Only Look Onse)と呼ばれるものがあり、CNN(Convolutional Neural Network:畳み込みニューラルネットワーク)を用いたアルゴリズムとなっています。2024年2月に最新の物体検出モデルYOLOv9が公開されています。

 本記事では、物体検出モデルYOLOv9で物体検出の動作環境構築と推論デモの実行を行います。

 

1. YOLOv9のリポジトリ

YOLOv9のGithubリポジトリは以下です。

github.com

2. 動作環境構築

以下のコマンドで動作環境を構築できます。

 

3. 推論デモ用の画像ダウンロード

次に推論で使用するサンプル画像をダウンロードします。今回は下記リンクの犬の画像を使用します。

https://media.roboflow.com/notebooks/examples/dog.jpeg

今回はyolov9ディレクトリ直下にdataフォルダを作成し、そこに画像を置きます。

 

4. 物体検出モデルのダウンロード

次に推論で使用するYOLOv9で提供されている事前学習済みモデル「gelan-c.pt」をダウンロードします。今回はyolov9ディレクトリ直下にweightsフォルダを作成し、そこにモデルをダウンロードします。

 

5. 物体検出の推論

では、最後に推論デモを実行したいと思います。「--source」の引数で画像の相対パスを指定しています。この引数に動画の相対パスを指定すると動画の推論が可能です。

上記のコマンドを実行すると、runs/detectの中にフォルダが作成されていると思います。そのフォルダの中に推論画像が保管されています。

「--source」の引数に動画ファイルの相対パスを指定して実行した際の推論結果動画の例は下記のようになります。

youtu.be

 

オススメ書籍

物体・画像認識と時系列データ処理入門

現場で使える!PyTorch開発入門 深層学習モデルの作成とアプリケーションへの実装

PyTorchで作る!深層学習モデル・AIアプリ開発入門

 


おわりに

本記事では、物体検出モデルYOLOv9の動作環境構築と推論デモの実行を行いました。かなりユーザーに優しい使用性ですので、どんどん活用が進みそうですね。

 

【Python】QRコードの生成と読み取り

1. はじめに

 本記事では、Pythonライブラリの「qrcodeを用いたQRコードの生成」と「pyzbarを用いたQRコードの読み取り」の基本的な手法を紹介します。

 

2. qrcodeを用いたQRコードの生成

まずはライブラリのインストールです。

qrcodeを用いたQRコードの生成は以下のプログラムでできます。

textの内容を変更することで様々な情報を埋め込むことができます。今回は本ブログのURLをtextとして設定し、QRコードを作成していきます。

 

上記のプログラムを実行すると、下記のようなQRコードが生成・保存されます。スマホ等のカメラアプリで読み込んでいただくと本ブログが表示されると思います。

 

3. pyzbarを用いたQRコードの読み取り

まずはライブラリのインストールです。

pyzbarを用いたQRコードの読み取りは以下のプログラムでできます。QRコードの読み取りデータからQRコードの座標、読み取ったデータ内容を再度画像に描画しています。ここでは上記で作成したQRコードを読み込んでいます。

上記を実行すると下図のような画像データが保存されます。QRコードの周囲を緑色の線で囲み、読み取ったデータを上部に記載しています。

なお、上記プログラムを実行した際のdecode_dataの中身は下記になっています。dataは読み取ったデータ、rectはQRコードの左上座標(left, top)と幅高さ(width、height)の長さ、polygonは多角形の座標を示しています。上記では多角形の座標を採用して描画しています。

 

なお、スマホカメラ、Webカメラ、IPカメラなどで撮影したカメラでは斜めになったり、そのままの画像ではダメで前処理が必要だったりするので、ご注意ください。

 

4. 参考ページ

qrcode · PyPI

pyzbar · PyPI

QRコードの生成と保存 | Python学習講座

【簡単】QRコードの作成と読み取り in Python #Python - Qiita

 

5. おわりに

 本記事では、Pythonライブラリの「qrcodeを用いたQRコードの生成」と「pyzbarを用いたQRコードの読み取り」の基本的な手法を紹介しました。QRコードを物体に貼付してカメラなどで読み取ることで、その物の判定ができたりするなど非常に便利なツールだと思うので、ぜひ活用してみてください。なお、スマホカメラ、Webカメラ、IPカメラなどで撮影したカメラでは斜めになったり、そのままの画像ではダメで前処理が必要だったりするので、ご注意ください。

PythonのTenacityを用いてリトライ処理

はじめに

 本記事では、Tenacityを用いたリトライ処理について簡単に紹介します。Tenacityは再試行動作を簡素的に実装できるライブラリで、2023年8月現在でもアップデートされています。

 本記事では基本的な処理として、以下を紹介します。

  1. リトライ処理の停止条件の設定
  2. リトライ処理の間の待機条件の設定
  3. 上記2つの組み合わせ

SAMURAI TERAKOYA

 

1. Tenacityについて

公式ドキュメントは以下になります。

Tenacity — Tenacity documentation

また、Githubリポジトリは以下になります。

github.com

ライブラリのインストールは下記のコマンドで実施できます。

 

2. リトライ処理の基本

リトライ処理の基本としては下記になります。リトライ処理対象の関数に「@retry」を付与します。なお、今回は「raise Exception」にて例外(エラー)を発生させて動作を確認します。

 

3. リトライ処理の停止条件の設定

 処理の再試行をしたい際に停止条件がない場合、永遠に処理を再試行します。そこで、停止条件を設けることで再試行を一定の条件で停止させます。なお、今回は「raise Exception」にて例外(エラー)を発生させて動作を確認します。

まず、下記は「5回再試行後に停止」する例です。「stop=stop_after_attempt(5)」を指定してあげることで5回再試行後にリトライ処理を停止することができます。

次に、「再試行を6秒実施したのちに停止」する例です。「stop=stop_after_delay(6)」を指定してあげることで6秒間再試行後にリトライ処理を停止することができます。

 

4. リトライ処理の間の待機条件の設定

続いては待機条件です。処理の再試行をしたい際にどのようなタイミングで再試行するかを設定できます。なお、今回は「raise Exception」にて例外(エラー)を発生させて動作を確認します。

まずは、「2秒間待機して再試行」する例です。「wait=wait_fixed(2)」を指定してあげることで、2秒ごとに再試行することができます。

次に、「ランダムな秒数待機して再試行」する例です。「wait=wait_random(min=1, max=2)」を指定してあげることで、1~2秒の間の時間で再試行することができます。

 

5. リトライ処理の停止条件と待機条件の組み合わせの設定

最後に、停止条件と待機条件の両方を設定してみます。なお、今回は「raise Exception」にて例外(エラー)を発生させて動作を確認します。

上記で示した5「5回再試行後に停止」と「2秒間ごとに再試行」の両条件を指定します。停止条件はstopで、待機条件はwaitでそれぞれ指定することで両条件を指定できます。下記の例を実行することで、それが実現できます。

 

SAMURAI TERAKOYA

おわりに

本記事では、Tenacityを用いたリトライ処理について簡単に紹介しました。システムからデータを出力する際やシステム間の接続の際に、出力ファイルが開かれている、接続の失敗で再試行をするケースが考えられます。その際に役立てれば幸いです。

【psutil】Pythonによるハードウェア情報の取得

はじめに

本記事では、psutilを用いてハードウェア情報を取得する方法を簡単にご紹介します。

 

1. psutil

psutilの公式ドキュメントは以下のリンクです。

psutil documentation — psutil 5.9.5 documentation

psutilはPythonで実行中のプロセスとシステム使用率(CPU、メモリ、ディスク、ネットワーク、センサー)に関する情報を取得するためのクロスプラットフォームライブラリです。

ライブラリのインストールは下記のコマンドを実行します。

 

2. CPU情報の取得

2.1 物理コア数

下記のコマンドで物理コア数を取得します。

2.2 論理コア数

下記のコマンドで論理コア数(スレッド数)を取得します。

2.3 CPU使用率

下記のコマンドでCPU使用率を取得します。単位はパーセントです。ここでintervalはCPU時間を指定します。ここではCPU時間1です。

また各CPUの使用率を取得するには下記のコマンドを使用します。

 

2.4 CPU周波数

CPU 周波数をMHzで表示します。現在の周波数、最大周波数、最小周波数を取得します。個別の周波数を取得することもできます。

 

2.5 CPU待ちタスク数

システムの全体的な負荷状況を知りたい時に使います。topコマンドのload averageと同じ情報です。1、5、15分間のCPUの処理を待っているタスクの数を表示します。

 

3. メモリ情報の取得

3.1 メモリの仕様に関する統計値(使用メモリ、空きメモリ等)

下記のコマンドでメモリの仕様に関する統計値を取得します。

各項目の意味は下表をご覧ください。

指標 意味
total 物理メモリの合計
available システムがスワップすることなく、プロセスに即座に与えることができるメモリ
percent (total - available) / total * 100で計算された使用率
used 使用されているメモリ
free 全く利用されていない、すぐ利用できるメモリ
active 現在使用中またはごく最近使用されたメモリ
inactive 未使用としてマークされているメモリ
buffers ファイル システムのメタデータなどのキャッシュ
cached さまざまなもののためのキャッシュ
shared 複数のプロセスが同時にアクセスできるメモリ
slab カーネル内のデータ構造キャッシュ

 

3.2 スワップメモリの仕様に関する統計値

システムスワップメモリ統計値を取得します。

各項目意味は下表をご覧ください。

指標 意味
total バイト単位の合計スワップメモリ
used 使用されたスワップメモリ (バイト単位)
free 空きスワップメモリ​​ (バイト単位)
percent (total - available) / total * 100で計算された使用率
sin システムがディスクからスワップインしたバイト数 (累積)
sout システムがディスクからスワップアウトしたバイト数 (累積)

 

4. ディスク情報の取得

4.1 パーティション

下記のコマンドでマウントされたすべてのパーティションを表示します。

各項目の意味は下表をご覧ください。

指標 意味
device バイスのパス
mountpoint マウント ポイントのパス
free 空きスワップメモリ​​ (バイト単位)
fstype パーティションファイルシステム
opts ドライブ/パーティションのさまざまなマウントオプションを示すカンマ区切りの文字列
maxfile ファイル名に指定できる最大長
maxpath パス名 (ディレクトリ名 + ベースファイル名) の最大長

4.2 ディスク使用統計値(合計領域、使用済み領域、空き領域 、使用率)

下記のコマンドでディスク使用統計値を取得します。バイト単位の合計領域、使用済み領域、空き領域 、使用率が表示されます。使用率などの個別の情報を取得することもできます。

4.3 システム全体のディスク I/O 統計値

下記のコマンドでシステム全体のディスク I/O 統計値を取得します。

各項目の意味は下表をご覧ください。

指標 意味
read_count 読み取り数
write_count 書き込み回数
read_bytes 読み取られたバイト数
write_bytes 書き込まれたバイト数
read_time ディスクからの読み取りに費やした時間 (ミリ秒単位)
write_time ディスクへの書き込みにかかった時間 (ミリ秒単位)
read_merged_count マージされた読み取りの数
write_merged_count マージされた書き込みの数
busy_time 実際の I/O に費やした時間 (ミリ秒単位)

 

5. ネットワーク情報の取得

5.1 ネットワーク I/O 統計値

下記のコマンドでネットワークI/Oの統計値を取得します。

各項目の意味は下表をご覧ください。

指標 意味
bytes_sent 送信されたバイト数
bytes_recv 受信したバイト数
packets_sent 送信されたパケットの数
packets_recv 受信したパケット数
errin 受信中のエラーの総数
errout 送信中のエラーの総数
dropin ドロップされた受信パケットの総数
dropout ドロップされた送信パケットの総数

 

5.2 ソケット接続情報

下記のコマンドでソケット接続情報を取得します。

各項目の意味は下表をご覧ください。

指標 意味
fd ソケットファイル記述子
family アドレスファミリ、AF_INET、AF_INET6またはAF_UNIXのいずれか。
type アドレスのタイプ ( SOCK_STREAM、SOCK_DGRAM、または SOCK_SEQPACKET )。
packets_recv 受信したパケット数
laddr ローカルアドレス(ip, port)
raddr リモートエンドポイントのアドレス(ip, port)
status TCP接続のステータス。UDPおよびUNIXソケットの場合、NONE
pid ソケットを開いたプロセスの PID

 

5.3 NICに関連付けられたアドレス、キーを表示

NIC (ネットワーク インターフェイス カード) に関連付けられたアドレスを、キーが NIC 名で、値が NIC に割り当てられた各アドレスの名前付きタプルのリストである辞書とします。

各項目の意味は下表をご覧ください。

指標 意味
family MACアドレスを参照するアドレスファミリ (AF_INET、AF_INET6、psutil.AF_LINK) 。
address NIC アドレス
netmask サブネットマスク
broadcast ブロードキャストアドレス
ptp ポイントツーポイントを表す。VPN上の宛先アドレス。

 

6. センサー情報の取得

6.1 ハードウェア温度

下記のプログラムでハードウェア温度(摂氏)を取得します。OSでセンサーがサポートされていない場合は空の辞書になります。

6.2 ファン速度

下記のプログラムでファン速度(単位rpm:1分あたりの回転数)を取得します。OSでセンサーがサポートされていない場合は空の辞書になります。

 

7. その他

7.1 システムの起動日時

下記のプログラムでシステムの起動日時を取得します。

7.2 システムに接続しているユーザー

下記のプログラムでシステムに接続しているユーザーを取得します。

各項目の意味は下表をご覧ください。

指標 意味
name ユーザーの名前
terminal ユーザーに関連付けられたttyまたは疑似tty
host エントリに関連付けられたホスト名
starting UNIXエポックからの経過ミリ秒数での作成時刻
pid ログインプロセスの PID

 

参考文献

psutil.readthedocs.io

blog.imind.jp

おわりに

本記事では、psutilを用いてハードウェア情報を取得する方法を簡単にご紹介しました。プログラムの実行時のハードウェアの情報や運用中のシステム状態監視などに活用できそうですね。

【logging】Pythonにおけるログ表示・出力

はじめに

 システムやプログラムを稼働・実行させている際にそのシステムやプログラムの状態の履歴の記録であるログを出力することが一般的です。特に異常時やエラー時等にログ内容から原因を究明して、改善・改良をすることがあることから、非常に重要な機能と言えます。

 Pythonにおいてもログをコマンドラインに表示したり、ログファイル(.log)として出力することができます。本記事では、loggingライブラリを用いてPythonプログラムのログを表示、出力する方法を簡単に紹介します。

1. loggingによるログ内容の説明ページ

 本記事ではloggingライブラリを用いてログ表示・出力を行います。ログ内容の説明ページを下記に示します。詳細などは下記のリンクに記載されていますので、お時間がある方はぜひご覧ください。

docs.python.org

docs.python.org

 

2. loggingによるログ出力

 loggingでは、DEBUG、INFO、WARNING,、ERROR、CRITICALの順の5段階レベルで出力することができます。ログレベルを指定しなければ、デフォルトのレベルは 「WARNING」になり、WARNING以上のログを出力します。

 まずは簡単な例で確認してみましょう。最初はログレベルを指定せずにログの出力を試みてみます。下記に例を記載します。

上記を実行すると、下記のようなログがコマンドラインに表示されます。ご覧の通り、ログレベルを指定していないので、WARNING以上のログを出力となっています。

 

3. ログレベルを指定してログ出力

次に、ログレベルを指定してログ出力を行います。ここではレベルを下げて、INFOレベルを指定して出力してみます。ログ仕様を指定するに際には、logging.basicConfig()を用います。logging.basicConfig()の引数levelにレベルを指定します。下記に例を示します。

上記の実行結果が下記になります。ご覧のようにINFOのログまで出力しています。こちらはご自身の開発仕様に合わせて変更してみてください。

 

4. ログのメッセージフォーマットを指定

次に、ログのメッセージフォーマットを指定してログ出力を行います。メッセージフォーマットであるLogRecord 属性の詳細はこちらに記載されています。

docs.python.org

代表的なものを抜粋して下表に示します。

属性名 フォーマット 説明
asctime %(asctime)s ログが記録された時刻
pathname %(pathname)s loggingの呼び出しが発せられたファイルの絶対パス
module %(module)s モジュール (filename の名前部分)
ファイル名 %(filename)s 実行プログラムの絶対パスのファイル名部分
funcName %(funcName)s loggingの呼び出しを含む関数の名前
levelname %(levelname)s メッセージのログレベル
lineno %(lineno)d loggingの呼び出しが発せられたソース行番号
message %(message)s ログメッセージ

 

それでは、メッセージフォーマットを指定してログ出力を行ってみたいと思います。まずは、「ログ記録時間」、「ログレベル」、「ログメッセージ」の3種類の情報を出力してみましょう。下記にそのプログラムを示します。

上記のプログラムを実行すると、下記のように「ログ記録時間」、「ログレベル」、「ログメッセージ」の3種類の情報を含むログが表示されます。

 

さらに、要素を増やして表示させてみましょう。「ログ記録時間」、「ログレベル」、「ログメッセージ」、「モジュール」、「loggingの呼び出しを含む関数の名前」、「loggingの呼び出しが発せられたソース行番号」の6種類の情報を出力します。下記にそのプログラムを示します。

上記のプログラムを実行すると、「ログ記録時間」、「ログレベル」、「ログメッセージ」、「モジュール」、「loggingの呼び出しを含む関数の名前」、「loggingの呼び出しが発せられたソース行番号」の6種類の情報が出力されます。さらに関数(cal)内で実行されたloggingについてはその関数内で実行されたことが確認できます。また、 %(lineno)dによりloggingの行数が表示されて、どこのログなのかが把握しやすくなりました。

 

5. ログ記録時間のフォーマット

 上記で「ログ記録時間」を表示していましが、このログ記録時間について表示形式を変更することが可能です。その際には、datefmtをlogging.basicConfig()の引数に指定することで実現可能です。フォーマット使用はtime.strftime()の仕様と同一です。

time --- 時刻データへのアクセスと変換 — Python 3.11.4 ドキュメント

それでは、ログ記録時間の表示形式を変更していきます。ここでは「%Y/%m/%d %H:%M:%S」の形式を指定し、その仕様で表示します。下記に例を示します。

上記のプログラムを実行すると、下記のような結果となります。時間の表示形式が「2023/07/08 15:10:43」のように変更されたことが確認できると思います。

 

6. ログファイルの出力

 さて、ここまで表示内容について説明をしていきましたが、その内容をログファイルとして出力していきたいと思います。ログファイルを出力するには、logging.basicConfig()の引数filepathに出力先のパスを指定してあげることです。ここでは、プログラムと同一のディレクトリに出力するために、「logfile_test.log」のようにログファイルのベースネームのみ記載します。

このプログラムを実行すると、コマンドラインには何も表示されずにログファイルが出力されます。そのログファイルの中にログが記載されていることが確認できるかと思います。

 

7. logging.exceptionによるエラー内容の表示

例えば以下のようにtry-except文で例外処理やエラーが発生する場合、特段その内容が表示されなくて、何が原因で例外処理・エラーになったのか不明なケースがあると思います。

本記事で示したlogging.error()でも下記のようにエラー内容が表示されない状況です。

 

このようにエラーが発生した際にどのようなエラーかが不明で、原因を特定するのが難しいです。そんな時、活躍するのがlogging.exception()です。logging.exceptionでは例外情報がメッセージ内容に追加されます。それでは、logging.exceptionを使ってその仕様を確認してみます。上記と同じtry-except文でプログラムを実行してみます。

実行した結果が下記になります。ご覧の通り、loggingのメッセージに加えてエラー内容が表示されています。これで原因究明をしやすくなりますね。

 

おわりに

本記事では、loggingライブラリを用いてPythonプログラムのログを表示、出力する方法を簡単に紹介しました。ログの表示仕様などはご自身の開発に内容に合わせて調整してみてください。そしてログ内容から開発促進、システムのイレギュラー対応などにご活用いただければ幸いです。