機械学習を使ってApexのプレイ動画から武器使用率を算出する

最終的な目標はプレイスタイルの解析 近年、動画投稿・配信サービスの普及により、ゲーム実況というものがエンタメの1カテゴリとして確立してきていると思う。感染症流行の影響が大きいと思うが、2021年1月~3月の主要ゲーム配信サイト(Twitch、YouTube Gaming、Facebook Gaming)の合計視聴時間が前年同期比で80%増加したというデータもある。1ゲームのジャンルとしてはアクション・RPG・シミュレーションなどあらゆるものが実況の対象になるが、今回はFPSのゲーム実況にスポットを当てる。 FPSの分野では、オンライン対戦システムおよび、いわゆるランクシステムが整備されているものが多くなっている。ランクシステムは、プレイヤーの習熟度のようなものを可視化する。こうしたランクに関する情報は、視聴者にとって、プレイヤーのことをパッと理解するために非常に役立っていると思う。 現状、ランク情報やダメージ数、キルデス比等はゲームシステムから参照できるようになっていることが多いと思う。ただ、個人的にはより細かい、プレイヤーのプレイスタイルのようなものを可視化できる情報があると、プレイヤーについて理解を深めるためのよい材料になると思った。 最終的にはゲームシステムから直接確認出来るデータだけでなく、ゲームプレイ動画の解析結果から、プレイヤーのプレイスタイルをうまく可視化したい。今回は、Apexを題材にし、プレイヤーのプレイスタイルを示す1つの指標として、武器使用率をゲームプレイ動画から解析できないか試す。まあ、こういった情報はわざわざ動画を解析しなくても、ゲームシステム側で実装してもらえれば、より正確で容易にデータが取れるとは思う。 全体の作業の流れ 今回の全体の作業の流れは以下のようになっている。 各作業の内容について説明していく。ただし、ゲームプレイ動画のキャプチャ作業については特に説明することがないので、何も説明しない。 武器名表示領域の切り取り データセットを整備するために、ゲーム画面のうち、武器名を表示している領域のみを切り取った画像を作成する必要がある。今回は、動画に対して一定時間ごとのフレームを画像化→特定領域を切り取り→特定の場所に画像ファイルとして保存、という流れでデータセット用の画像を作成した。 一連の画像切り取り作業実施のために、ツールを作成した。GUI部分はPySimpleGUIを利用している。 主に以下を設定できる。 切り取り対象とする動画の保存場所 武器1欄(*1)の画像を保存する場所 武器2欄(*1)の画像を保存する場所 画像を切り抜く領域(*2)(全体サイズに対する割合で指定) (*2)で設定した領域からどれだけずらした画像を何個保存するか 画像切り取り対象とするフレームの時間間隔 (*1)Apexでは、武器を同時に2つ持つことができる。今回は武器1欄と武器2欄を別々のデータセットとして扱う。理由はそちらの方がより精度が上がりそうと思ったためである。 このツールを使えば、ボタンを1回ポチーすることで、後は待っていれば所定の場所に武器名表示領域の画像が保存される。 画像に対して正解ラベルを付ける データセットの正解ラベル付けについて、どのような形式で保存するのが一般的かを私は知らないのだが、今回は各正解ラベル(武器名)ごとに保存フォルダを分けることにした。 以下のように、全武器+“武器なし”(_None)について画像をフォルダ分けした。 この作業にも専用ツールを作成した。 データセットが置かれている場所を指定して、startボタンを押すと、所定の個数づつ未分類の画像が表示される。表示された画像について、正解となる武器名のボタンをポチポチしていき、画像をフォルダ分けする。 ただ、今回データセットの元にしたキャプチャ動画は武器を決まった順番で使うようにしていた。そのため、切り抜かれた画像が最初から決まった武器順で並んでおり、結局このツールはあまり使わなかった。 学習・モデルの保存 データセットの準備が出来たので、ようやく学習をする。学習部分はコードベースで説明する。 まず、データセットの読み込みを行う。かなりコードが汚い。武器名のリストは、以下のコードに含まれていない関数を使ってファイルから読みこんでいる。 Kerasを用いてモデルを生成する関数を作成する。 Optunaを使ってハイパーパラメータを調整しつつ、成績の良いモデルを保存する。(といってもマシンが貧弱で学習に時間がかかるので、5回しか試行を回していない。) 上記のコードを実行したところ、とりあえず今回はテストデータの正解率が99.89%のモデルが出来た。テストデータの推論結果をMatplotlibを使って画像とともに確認してみる。 いい感じに推論できてそうだ。誤答をしたデータについても確認してみる。 今回は2つのデータの推論が間違っていたようだ。上は正答がFlatlineなのに対し、Devotionと推論してしまっており、下は正答がNoneなのに対し、R-301と推論してしまっている。 作成したモデルによるプレイ動画の解析 モデルが出来たので、動画を解析する。解析用のソフトを作成した。 学習用に使ったデータとは別のキャプチャ動画を使って解析したところ、以下のような結果になった。 解析結果を見たところ、大体は合っていると思うが、誤検出されている武器名が末尾に並んでいる。解析結果は正確なものではないため、データの扱いは少し考えないといけない。 最初は自作モデルを作らなくても行けると思っていた 今回、武器使用率算出のために"機械学習のモデルを作成・利用する"という手段を選択した。 この手段を取る前は、TesseractとPyOCRを利用して文字列を認識する方法をとっていた。ただ、認識精度が厳しかったので、利用を断念した。機械学習の勉強にもなると思い、代わりに自作モデルの作成という方法をとった。 今回の識別対象は決まり切った文字列なので、機械学習を使わなくても、より正確な認識方法があるかもしれない。というか、私はApexにあまり詳しくないので、そもそもゲームシステム内で武器使用率を確認できる方法があるかもしれない。 参考にした書籍・動画 機械学習については主にネット上の情報と、以下の書籍の内容を流し読みした程度の理解度である。 ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 オライリージャパン (2016/9/24) Amazon 楽天市場 また、上記書籍を数年前に読んだときは誤差逆伝播法がいまいち理解できなかった。しかし、Twitterのタイムラインで流れてきた以下の動画が非常に参考になり、とりあえず分かった気にはなれた。出来るだけ条件を簡易にして、高校数学の範囲で説明されている。 まとめ 機械学習を利用してApexのプレイ動画から武器使用率を算出するためのツール群を作成した。解析結果には誤差が含まれるため、利用するためにはまだ工夫をする必要があると思う。 色々試行錯誤をする中で、モデルの性能に最も寄与したのはデータセットの作り方だった。データセットに偏りがあると、それを学習したモデルも偏りのある結果を出力する。データセットの質の重要性を、身をもって実感した。この部分については本記事で書けなかったので、またどこかで記事を書くかもしれない。 Q1 2021 Live Game Streaming Trends - Stream Hatchet ↩︎...

November 1, 2021 · 1 min

顔認識+サーボモーターで顔追従モニターの作成

先日、NT金沢2021というイベントに、リモートで出展参加した。「リモートで出展参加」というのは、具体的に言うと、展示物としてはオンラインで遊べるものをポスターで出展して、私はGoogleMeet(ビデオ会議)をつないでリモートで一部作品の説明をしていた。(関係機材は現地出展した友人に運んでもらった。) GoogleMeetをつなぐには、とりあえずPCが現地(NT金沢の会場)にあれば事足りる。ただせっかくなので、モニターが、話している相手の顔を追跡するようにした。 動作の様子 人の顔に追従するモニタを試作中…。 ■使用素材 画像:いらすとや(https://t.co/H01vPNj6QI) pic.twitter.com/H8fLDuSRjz — 青木晃也 (@aoki_kouya) May 30, 2021 検証時の動画だが、概ね完成形。当日はこのモニターに、GoogleMeetの画面を表示して運用していた。 ハードウェア 使用部品一覧 部品名 備考 JetsonNano開発者キット 顔認識・ビデオ会議・サーボ制御用 Webカメラ×2 1個は顔認識用、1個はビデオ会議用 モニター スピーカーも内蔵 サーボモーター S03T/2BBMG/F×2 強そうなものをチョイス PCA9685モジュール サーボ制御用 サーボやモニタ等を固定するための部品は3Dプリンターで作成した。 WebカメラはとりあえずAmazonで安いものを適当に買った。1種類目はUSB Wi-Fi子機との相性が良くなかったようで、Wi-Fiの接続が不安定になった。2種類目は特に問題なく動いていそうだったので、採用した。ただ、この記事を書いている時点で、採用したWebカメラのAmazonの商品ページはリンク切れになっていた。 ソフトウェア ソフトウェアに関する部分としては、JetsonNano起動後にコンソールで顔追従用プログラムを実行した後、ブラウザ(Chromium)でGoogleMeetを動かしていた。GoogleMeetの方は特に書くことがないため、顔追従用プログラムのソースコード及びセットアップ周りを書いていく。 顔追従用プログラムのソース ソースは以下に置いてある。 顔追従用プログラムのセットアップ周り 上記のソースを動かすには、関係ライブラリをインストールする必要がある。 PCA9685用ライブラリのインストール サーボ制御モジュールPCA9685をPythonから制御するためのPythonパッケージをインストールする。まず以下のコマンドでpip3をインストールする。 sudo apt-get install python3-pip 参考元: NVIDIA Jetson Nano 開発者キットに TensorFlow をインストールする - Qiita...

July 23, 2021 · 1 min

ロジスティック回帰を使ってYouTubeタイトルから投稿者を推論する

Pythonでロジスティック回帰を使って、VTuberの動画タイトルから投稿者を推論してみる。 ただ、投稿者を推論するといっても、二値分類なので、投稿者が A か B かを分類するのみ。 使用するライブラリ 今回は以下のライブラリを使用する。 scikit-learn : テキストのベクトル化、ロジスティック回帰 MeCab : 日本語形態素解析 データセット 適当に選んだRan Channel / 日ノ隈らん 【あにまーれ】さんとKuzuha Channelさんの動画タイトルをデータセットとして使う。 動画タイトルはYouTube Data APIを使って取得した。 1日のAPIリクエスト上限に引っかかって、すべては取得できなかったが、日ノ隈らんさんのタイトルは475個、葛葉さんのタイトルは456個取得できた。 タイトル取得に使用したプログラムは以下に置いてある。 また、タイトル中の【】内には大体投稿者名が入っている。 これを使うと簡単に分類できてしまうと思うので、今回は削除する。 (まあ、【】内でなくても、投稿者名が入っていることがあるので結局、というところもあるが…) プログラムと推論結果 今回推論に使用したプログラムは以下に置いてある。 テストデータは直近(このプログラムを作成中)に投稿された以下のタイトルを使う。 Ice breaker / ChroNoiR けんきさんとあびつんさんとランクいってくる!!! 1行目が葛葉さんの動画タイトルで、2行目が日ノ隈らんさんの動画タイトルになっている。 推論結果 推論結果は以下のようになった。 [0.45 0.69] なお、1個目が1行目の結果で、2個目が2行目の結果になる。 また、この結果が 1.0 に近いほど日ノ隈らんさんのタイトル、 0 に近いほど葛葉さんのタイトル"っぽい"と判断できる。 推論結果の分析 どういった理由で今回の推論結果が出たのか分析する。 ロジスティック回帰では各特徴量の係数(重み)と切片(バイアス)を見ることができる。 今回の特徴量はタイトルに含まれる単語なので、各単語について係数(重み)を見てみる。 まず1行目のタイトルの各単語の結果は以下の通り。 以下でwordとtf_idfというラベルで出力しているものが、それぞれ単語名及びtf-idfという手法によって得られた、各単語の重要度になる。 ただ、このデータに関してはすべての単語について、学習元データに含まれていなかったため、this word does not existと表示されている。 つまり、上記推論結果で0.45と出ているが、これは切片(バイアス)成分によるものである。 title_index: 0 word: Ice tf_idf: this word dose not exist word: breaker tf_idf: this word dose not exist word: / tf_idf: this word dose not exist word: ChroNoiR tf_idf: this word dose not exist 次に2行目のタイトルの各単語の結果は以下の通り。...

May 25, 2020 · 2 min

LogisticRegression().fit()のConvergenceWarningを解消する

環境 Anacondaの環境情報 >conda info conda version : 4.8.2 conda-build version : 3.18.11 python version : 3.7.6.final.0 platform : win-64 現象 pythonでLogisticRegression.fit()を実行したところ、以下のワーニングが出た。 ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. 実行時のjupyter notebookは以下のような感じ。 一応正解率は出せているらしい。 解決策の1つ モデルが収束していないそうなので、max_iterを明示的に設定して、反復回数を増やす。 max_iterの初期値は100だが、上の例では1000に設定している。 今回はこれで警告が出なくなったので、よしとする。 参考 見て試してわかる機械学習アルゴリズムの仕組み 機械学習図鑑posted with ヨメレバ秋庭 伸也/杉山 阿聖 翔泳社 2019年04月17日 楽天ブックスで購入楽天koboで購入Amazonで購入Kindleで購入

May 16, 2020 · 1 min