テニスにおける打球方向の予測を行いたいと思ってるのですがデータセットを作る際正解データをどこに記せば良いのかがわかりません。
打球時から20フレーム前までの選手の位置座標と選手の関節位置座標から打球方向のクラスを出力するLSTMモデルを組もうと考えています。個人的には打球方向をどこに記せば良いのかがよくわかっていません。
自分でも各業にそれぞれ正解データを降るのはおかしいと思っていますがどのようにすれば良いのかがわかりません。
現状自分が作っっているデータセットをイメージとして載せておきます。
はじめの二列が選手のコート内の座標でそこから26列が選手の関節の座標で最後の一列が打球のコースになります。
各行に1フレーム分の座標情報になります。
20行ごとに1回打球のコースをstraight,leftcross,rightcrossの3クラスとして出力したいと思っています。
機械学習初心者のため拙い説明担ってしまい申し訳ありません。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/12/31 20:17
2023/01/01 00:17 編集
回答1件
0
ベストアンサー
各行にそれぞれ正解データを振るのはおかしいと思っています
普通は,画像/時系列データ等の非構造化データの場合,1フォルダに1クラス,1ファイルに1データが基本です.したがって,次のようなディレクトリ構造にするのが多いです.波形データであればkeras.utils.audio_dataset_from_directoryが使えるぐらい一般的な構造です.
dataset ├── straight │ ├── 01.csv │ ├── 02.csv │ └── ... ├── leftcross │ ├── 01.csv │ ├── 02.csv │ └── ... └── rightcross ├── 01.csv ├── 02.csv └── ...
例えば,SIGNATEの練習問題株価の推移予測では,最後の行にのみ,出力したいデータが挿入されています.同様に,質問にあるように各行に出力したいデータを挿入したとしても,コードを記述して機械学習で扱えるデータに変換すればよいだけのことです.ちなみに,このような一般的でないデータの場合,学習可能な形式に変換するライブラリは存在しません.ひたすら自分でコードを書くしかないです.
データセットを作る際出力データをどこに記せば良いのか
出力データを記す位置は,入力データとの対応関係がとれるのであればどこでも良いです.どんな構造であれ,最終的にモデルに与える入力データ配列x
のi
番目にアクセスしたときの内容は,出力データ配列y
のi
番目の内容を意味するよう,プログラムを組むことになります.この対応関係が取り出せれば,上のようなディレクトリ構造であっても,質問のようなCSVファイルでも大丈夫です.自分がコードを書きやすいようにCSVファイルを作ったらいいんじゃないでしょうか.
今回の目的に応じたデータ加工の最終目標は,入力データの形状が(100, 20, 28)
,出力データの形状が(100, 3)
になることです.特に入力のデータ形状はLSTMが扱える形式になっています.データのi
番目だけの単一のデータをモデルに与えた場合,次のように入出力されることが期待されます.
この状態を目指せるデータセットを構築するまでのことです.
以下余談
以下にコードを例示します.画像で示しているdataset.csvをpandas.read_csv("dataset.csv")
で読み込むことが可能です.ファイルパスは適宜環境に合わせてください.
前回の質問で得られた解答にあるような,chunksize = 20
の指定と同等の動作を,スライスを利用して実現しています.念のため,各行に割り振ったstraight, leftcross, rightcrossが20行(1データ分)の間で一致しなかった場合assertion errorを吐くようにしてあります.
Python
1from sklearn.preprocessing import OneHotEncoder, StandardScaler 2from sklearn.model_selection import train_test_split 3 4import numpy as np 5import pandas as pd 6import random 7 8# raw_data = pd.read_csv("dataset.csv").values と同等の疑似データを作成する. 9raw_data = list() 10for i in range(100): # 100打球分 11 shoot_type = random.sample(["straight", "leftcross", "rightcross"], 1)[0] 12 for k in range(20): # pre shoot behavior 13 d = [random.gauss(0, 100) for _ in range(28)] 14 d.append(shoot_type) 15 raw_data.append(d) 16raw_data = np.array(raw_data) 17# 作成完了, raw_data.shape = (2000, 29) のはず. 18 19# 前処理フェーズ 20# 入力データをFeature-wiseでZ-Score Normalizationする. 21ss = StandardScaler() 22raw_data[:, :-1] = ss.fit_transform(raw_data[:, :-1].astype(np.float32)) 23 24x, y = list(), list() # 入力データxと出力データyに整形する. 25for i in range(0, len(raw_data), 20): 26 x.append(raw_data[i: i + 20, :-1]) # 入力データを取得 27 assert len(np.unique(raw_data[i: i + 20, -1])) == 1, f"wrong data format at {i} to {i+20}, {raw_data[i: i + 20]}" 28 y.append(raw_data[i, -1]) # 出力データを取得 29x = np.array(x).astype(np.float32) 30print(x.shape) # (100, 20, 28) になっているはず.100件,タイムスタンプ20点,特徴量28個を意味する 31 32# 出力データをOne-Hot Encodingする. 33ohe = OneHotEncoder() 34y = ohe.fit_transform(y.reshape(-1, 1)).toarray() 35print(y.shape) # (100, 3) になっているはず.100件,3クラスを意味する 36 37x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.1) # 1割をテストデータにする. 38# 前処理フェーズ終了
タグがKerasなので,このままKerasで書き進めると,次のように学習が可能です.
Python
1from keras.layers import Input, Dense, LSTM 2from keras.models import Sequential 3from keras.optimizers import Adam 4from keras.callbacks import EarlyStopping, ReduceLROnPlateau 5from keras.utils import plot_model 6from sklearn.metrics import accuracy_score, confusion_matrix 7 8# 単純なLSTMモデルを作成する. 9model = Sequential() 10model.add(Input(shape = (20, 28))) # Timestampが20件, Featureが28件のデータから予測したい 11model.add(LSTM(32)) 12model.add(Dense(3, activation = "softmax")) # 3クラスを予測する. 13# モデル作成完了. 14 15# モデルの状態を確認する. 16model.summary() 17plot_model( # required graphviz 18 model, 19 to_file = "model.png", 20 show_shapes = True, 21 show_layer_names = True, 22 show_layer_activations = True 23) 24# モデルの損失関数と最適化関数,学習過程で監視したいMetricsを設定 25model.compile( 26 loss = "categorical_crossentropy", 27 optimizer = Adam(learning_rate = 0.001), 28 metrics = ["acc"] 29) 30 31# 学習が停滞(学習曲線がPlateau状態)していたら,学習率LRを減少Reduceさせる. 32rlr = ReduceLROnPlateau( 33 patience = 5, # 5epoch間で 34 monitor = "loss", # lossの 35 mode = "min", # 最低値minが更新されなかったら 36 factor = 0.5, # 学習率を0.5倍にする 37 verbose = 0, 38) 39 40# 学習 41model.fit( 42 x_train, y_train, 43 batch_size = 32, 44 epochs = 256, 45 validation_split = 0.1, # trainデータから更に1割を検証用データにする 46 callbacks = [rlr] 47) 48 49# テスト 50y_test = np.argmax(y_test, axis = -1) 51y_pred = np.argmax(model.predict(x_test), axis = -1) 52print(f"Confusion Matrix\n{confusion_matrix(y_test, y_pred)}") 53print(f"Accuracy Score\n{accuracy_score(y_test, y_pred)}")
今回かなり適当に書き進めましたが,学習において全て正しい手法/値を利用しているというわけではないことに注意してください.全ての入力においてStandardScaler
によるFeature-wiseな標準化をしていることや,テストデータおよび検証データの利用にあたっては乱数で適当に分割しているだけですし,LSTM内のユニット数を適当に32で決めていたり,オプティマイザにAdamの利用をしたり学習率を0.001にしたり,バッチサイズを32にしたりなどしているため,調整の余地しかないです.
少なくとも,データの整形/前処理に関して学習されることから始められることを推奨します.次に列挙する資料の確認をしてください.
- sklearn.preprocessing: 正規化に関して
- 前処理22-23行目: 正規化方法はZ-Scoreのみならず,他にもMin-Max Normalizatinなどがあること.
- 今回はFeature-wiseに正規化したが,他にもDataset-wise, Sample-wiseな正規化があること.
- 前処理34-35行目: OneHot Encodingの動作について.
- 前処理22-23行目: 正規化方法はZ-Scoreのみならず,他にもMin-Max Normalizatinなどがあること.
- sklearn.model_selection: 交叉検証に関して
- 今回は簡単に
train_test_split
でデータの分割を済ませたが,本来であれば交叉検証によるモデルの最適化が必要であること.
- 今回は簡単に
今回コードに含まれていませんが,CSVファイルを見る限り座標が0になっている箇所は欠損値かと存じます,これらを補間する手法も多岐にわたるので調べて実装なさった方が良いでしょう.
また,SIGNATEにはテニスの勝敗予測をする練習問題があるので,初手で時系列データに取り組んでわけわからないまま進めるよりは,このような単純なテーブルデータから取り組んでみても良いでしょう.少なくとも勝敗予測できなければ,時系列データなんて予測できないと思います.
まとめ
- 出力データを記す位置は,入力データとの対応関係がとれるのであればどこでも良い
- フォルダごとにクラスで分ける,行末に記す,別ファイルに記す,データベースを利用する等
- Neural Networkの利用を前提としているなら,データの前処理の知識が必要不可欠であること.Garbage In, Garbage Outである.
- 初手で独自データの解析をすると痛い目を見る(見た)
投稿2022/12/31 23:48
編集2023/01/01 00:56総合スコア1579
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/01/01 02:53
2023/01/02 02:08
2023/01/02 02:18 編集
2023/01/02 02:23
2023/01/02 07:56
2023/01/02 10:58
2023/01/08 13:23
2023/01/08 16:26 編集
2023/01/19 00:13
2023/01/19 00:39
2023/01/19 03:30
2023/01/20 18:10
2023/01/21 22:03 編集
2023/01/23 11:49
2023/01/23 11:51
2023/01/23 12:51
2023/01/23 13:10
2023/01/23 13:50
2023/01/23 17:42
2023/01/24 04:45
2023/01/24 06:44
2023/01/24 06:45
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。