質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

scikit-learn

scikit-learnは、Pythonで使用できるオープンソースプロジェクトの機械学習用ライブラリです。多くの機械学習アルゴリズムが実装されていますが、どのアルゴリズムも同じような書き方で利用できます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2611閲覧

時系列データを二値分類(一次元畳み込み)

KYuki1218

総合スコア26

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

scikit-learn

scikit-learnは、Pythonで使用できるオープンソースプロジェクトの機械学習用ライブラリです。多くの機械学習アルゴリズムが実装されていますが、どのアルゴリズムも同じような書き方で利用できます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2023/02/06 10:27

編集2023/02/09 12:31

実現したいこと

健常者(normal)と障害者(abnormal)のそれぞれかmediapipeで得られたデータを学習させ,分類していない未知のデータを読み込み,正常か異常の判定を行う分類モデルを作成したいです。

前提

ps_aux_grep様が記載しているコード(リンク内容)を参考に,私が所持しているデータで試したところ,下記のようなエラーメッセージが生じ,解決方法がわからない状況です…どこをどのように修正すればよろしいでしょうか。

所持しているデータ(normalデータ1例)
列名は全て同じですが(89列),行数はデータによって異なります(測定時間が異なる)。

idxpelvis.xpelvis.ypelvis.zleft_hip.xleft_hip.yleft_hip.zright_heel.yright_heel.z
0-1437.3-1.91591.-1357.581.11592.4-359.81133.0
1-1429.4-9.11590.7-1357.577.41592.1-300.31128.2
2-1420.2-68.31575.7-1348.419.01578.6-347.01102.4
890-1464.9-210.81552.9-100.11566.6-1495.7-393.11043.5

発生している問題・エラーメッセージ

Input 0 of layer "conv1d" is incompatible with the layer: expected min_ndim=3, found ndim=1. Full shape received: (None,)

該当のソースコード

python

1import numpy as np 2from glob import glob 3import csv 4import os 5from sklearn.preprocessing import StandardScaler 6 7def load_csv(file, y_value): # ファイル名fileのCSV読み込み,1データを複数に分割する 8 # pandas.read_csv()を使わないで書いてみる 9 _x = list() # 1ファイルのデータすべて_xに格納する 10 with open(file, "r") as f: 11 reader = csv.reader(f) 12 header = next(reader) # ヘッダは読み飛ばし 13 for row in reader: 14 _x.append([float(col) for col in row[8:25]]) 15 16 # データ分割部 17 _x = np.array(_x) 18 roll = 215 19 x, y = list(), list() 20 for r in range(len(_x) - roll): # 2割のデータ長さだけデータが作られる. 21 x.append(StandardScaler().fit_transform(_x[r: r + roll].reshape(-1, 1)).reshape(_x[r: r + roll].shape)) 22 y.append([y_value]) 23 return np.array(x), np.array(y) 24 25def load_data(): # 全データ読み込み 26 split = 20 # 最初の20ファイルは検証用データにする 27 x_train, y_train, x_valid, y_valid = list(), list(), list(), list() 28 for name, v in zip(["mormal", "abnormal"], [0, 1]): 29 for i, file in enumerate(glob(f"/content/drive/MyDrive/data/{name}/*.csv")): 30 print(file) 31 _x, _y = load_csv(file, v) 32 if i < split: 33 x_valid.extend(_x) 34 y_valid.extend(_y) 35 else: 36 x_train.extend(_x) 37 y_train.extend(_y) 38 39 return map(np.array, [x_train, y_train, x_valid, y_valid]) 40 41x_train, y_train, x_valid, y_valid = load_data() 42print(x_train.shape) 43 44import tensorflow as tf 45from tensorflow.python import keras 46from keras.models import Sequential 47from keras.layers import Conv1D, Input, Flatten, Dense, AveragePooling1D, GlobalAveragePooling1D 48from keras.optimizers import Adam 49 50from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay 51from sklearn.metrics import confusion_matrix 52from sklearn.metrics import accuracy_score 53from sklearn.metrics import precision_score 54from sklearn.metrics import recall_score 55from sklearn.metrics import f1_score 56 57# 学習モデルを作成 58model = Sequential() 59model.add(Input(shape = x_train.shape[1:])) 60model.add(Conv1D(64, 8, activation = "swish", kernel_initializer = "he_uniform")) 61model.add(AveragePooling1D()) 62model.add(Conv1D(128, 4, activation = "swish", kernel_initializer = "he_uniform")) 63model.add(AveragePooling1D()) 64model.add(Conv1D(256, 3, activation = "swish", kernel_initializer = "he_uniform")) 65model.add(GlobalAveragePooling1D()) 66model.add(Dense(1, activation = "sigmoid")) 67 68model.compile( 69 loss = "binary_crossentropy", 70 optimizer = Adam() 71) 72model.summary() # モデル確認用 73 74# 学習モデルにデータを与えて学習させる 75model.fit( 76 x_train, y_train, 77 batch_size = 8, 78 epochs = 50, 79 class_weight = {0: 4, 1: 1}, 80 validation_data = (x_valid, y_valid) 81) 82 83# テストデータを与えて各データの種類を推測 84# 0から1の 範囲 で得られるのでroundで 四捨五入して0か1にする 85y_pred = np.round(model.predict(x_valid, batch_size = 8)) 86 87#混同行列 88tn, fp, fn, tp = confusion_matrix(y_valid, y_pred).ravel() #混同行列のそれぞれの結果を取得 89print("TN", tn) 90print("FP", fp) 91print("FN", fn) 92print("TP", tp) 93 94#正解率(Accuracy) 95score = accuracy_score(y_valid, y_pred) 96print(f"正解率:{score * 100}%") 97 98#適合率(Precision) 99print('Precision:', precision_score(y_valid,y_pred)) 100 101#再現率(Recall) 102print('Recall:', recall_score(y_valid,y_pred)) 103 104#F値(F-measure) 105print('F1 score:', f1_score(y_valid,y_pred)) 106print("Classification report")

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

PondVillege

2023/02/06 11:47 編集

行数はデータによって異なりますとのことですので, roll = int(len(_x) * 0.8) としているところを,全てのcsvの行数のうち,最低行数より少し小さい値をrollに入れてみてください. また,89列のデータを使うには,12行目の _x.append([float(col) for col in row[:3]]) を _x.append([float(col) for col in row]) にしてみてください.
jbpb0

2023/02/06 11:46

> 89行のデータを使うには 89「列」のデータを使うには、ですよね
PondVillege

2023/02/06 11:48

jbpb0さん,ありがとうございます. Muuuukiさん,可能であれば変更前の39行目時点のx_train.shape及び変更後のx_train.shapeも示していただけると助かります.
KYuki1218

2023/02/06 13:26

ps_aux_grep様,コメントいただき嬉しい限りです! プログラミングを初めてまだ日が浅く,理解が及ぼないのですが…「roll = int(len(_x) * 0.8)としているところを,全てのcsvの行数のうち,最低行数より少し小さい値をrollに入れてみてください.」とは,具体的にはどのように変更すればよろしいでしょうか?
PondVillege

2023/02/06 13:45 編集

./data/normal/や./data/abnormal/にたくさんのCSVが入っていると存じます.このCSVの行数を自身で調査なさって,int(len(_x) * 0.8)の代わりに一番小さい行数より小さい整数値をrollに代入してください.ということです.このint(len(_x) * 0.8)はすべてのCSVの行数が同じであったケースに適用できるコードなのですが,現状CSVごとに行数が異なるとのことですので,何かしらの値を決め打ちで入れる必要があります.CSVの行数が一番少ないもので100とかであれば,roll = 95とかにしてやってください. 手作業で行数を調べるのがめんどいので, https://teratail.com/questions/3xfudl9u3h80at に示す min_row = min([x.shape[0] for v in data.values() for x in v]) のようにして一括で最低行数を調べることも可能です.ここではroll = int(min_row * 0.9)として最低行数より少し小さい値(0.9倍の値)をrollに入れています.
KYuki1218

2023/02/06 13:48

具体的にありがとうございます。理解できました! rollに入れるべき数値を探索してみて,rollの数値入力,12行目の変更をする前後のx_train.shapeをお示ししますため,少々お時間をいただけますと幸いです。
KYuki1218

2023/02/06 14:06

変更前,変更後ともに(0,)出力されました。これは正しい出力でしょうか。なお,変更後はrollを215にして,12行目の[:3]という記載を削除しております。
jbpb0

2023/02/06 14:12

normalとabnormalのcsvファイルは、それぞれいくつありますでしょうか?
PondVillege

2023/02/06 14:34 編集

なるほど,CSVはPythonスクリプトがある場所との相対パスで./data/normal/や./data/abnormal/の中にないといけないのですが,これは守られているでしょうか.上のコードで言うところの27~28行目の間でfileをprintしてみて,何も出なければglobによるCSVファイル一覧取得ができておらず,データが読み込めていないことになります.必ずしも./data/の中になくて結構です.ちゃんとCSVファイルがある場所を指定してください.
KYuki1218

2023/02/06 14:21

jbpb0様,normal46データとabnormalは120データございます。
KYuki1218

2023/02/06 14:28

ps_aux_grep様,ご指摘通り,nameをprintすると name 'name' is not definedと出力されるため,読み込めていないことが問題かと思われます。初歩的な内容で申し訳ないのですが,/content/drive/MyDrive/data/normalにデータがあり,どの行をどのように変更すればよろしいでしょうか。
PondVillege

2023/02/06 14:40 編集

では, glob(f"./data/{name}/*.csv")のところを glob(f"/content/drive/MyDrive/data/{name}/*.csv") のように絶対パス指定にしてください. また,27~28行目にprint(file)をやってみてください(すみません,さっきはnameと言いましたが正しくはfileです.name is not defined. と出たということは書く場所が間違ってそうです.再度確認をお願いします).
jbpb0

2023/02/06 14:47

> /content/drive/MyDrive/data/normalにデータがあり normalのcsvファイルはそこでいいですが、abnormalのcsvファイルは /content/drive/MyDrive/data/abnormal に置いてください
jbpb0

2023/02/06 14:52

「print(file)」を追加するのは、「_x, _y = load_csv(file, v)」のすぐ上です
KYuki1218

2023/02/06 14:52

ご教示いただいた内容で実行したところ,RAMがクラッシュしてしまいます…一時的にgoogle proにして,ハイメモリにしても解決しません。もう少し解決方法を確認してみます。
KYuki1218

2023/02/06 14:57

jbpb0様,具体的にありがとうございます!ご教示いただいた修正をした上で実行すると,読み込んでいるファイル名が視覚的にみられるのですが,全てを読み込んだ後にRAMがクラッシュしたというアラートが出てくる状況です…
jbpb0

2023/02/06 15:11 編集

> RAMがクラッシュ ということは、csvファイルは読めたのですかね? 上記がyesならば、(可能なら)「x_train.shape」を教えてください
jbpb0

2023/02/06 15:13

> rollを215 を減らすか、 > 12行目の[:3]という記載を削除 を元に戻して、「3」を「89」以下で調節するかしたら、クラッシュしにくくなると思います ただし、それはデータを捨てることになります 前者は、時間を短くすることです 後者は、体の測定箇所を減らすことです あとは、csvファイル数を減らすか
PondVillege

2023/02/06 15:17 編集

rollを利用して18行目のループでデータを増やしているので,このループを削減するのもよさそうですね.
KYuki1218

2023/02/06 15:17

Google colabで実行したら途中でクラッシュしたという表記が出て,読み込む途中で中断されました。 変更前:(21955,) 変更後:(82436, 215, 89) jupyter notebookで出力したところ,上記のような結果が得られました。もし今後の学習モデルを作成する際にjupyter notebookだと不都合がある場合は,どうにかGoogle colabで実行できるように,ご教示いただいた方法で進めてみますが,jupyter notebookでも問題ないでしょうか。なお,PCはmacbook airでM1です。
KYuki1218

2023/02/06 15:20

rollを削除するというのは下記の部分を削除するということでしょうか? for r in range(len(_x) - roll): # 2割のデータ長さだけデータが作られる. x.append(_x[r: r + roll]) y.append([y_value])
PondVillege

2023/02/06 15:24 編集

M1ならGoogle Colabの方が良いです. 現状,1つのCSVファイルを18行目のループ for r in range(len(_x) - roll): で増やすようにしていますが,これを変更して for r in range(n): とかにしてみてください.nは任意の少ない数字で結構です(5 ~ 10とか).これである程度メモリを食わずに済みますが,CSVファイルのデータ全体をモデルに食わせることができなくなります. 解決策としてDataLoaderを作成する方法があります.この方法だとデータを全てメモリに載せる状態なしで,CSVファイルに存在するデータ全てを学習可能です.
jbpb0

2023/02/06 15:30

macはgpuが使えないため学習が遅いので、google colabの方がいいですよ
KYuki1218

2023/02/06 15:34

お二人とも懇切丁寧にご指導いただき心より感謝申し上げます。 for r in range(10):に変更したところ,x_train.shapeは(1260, 215, 89)と出力され,最後まで実行したところ(気が早いですが…)正解率:56.49%でした。この精度を高めるためには,DataLoaderというものを使用する方が良いでしょうか。
PondVillege

2023/02/06 15:53 編集

56%ということは適当にサイコロ振って答えるのとあまり変わらないですね, 単純にモデルの性能が低いかもしれないので, model = Sequential() model.add(Input(shape = x_train.shape[1:])) model.add(Conv1D(8, 64, activation = "swish", kernel_initializer = "he_uniform")) model.add(AveragePooling1D()) model.add(Conv1D(4, 128, activation = "swish", kernel_initializer = "he_uniform")) model.add(AveragePooling1D()) model.add(Conv1D(3, 256, activation = "swish", kernel_initializer = "he_uniform")) model.add(GlobalAveragePooling1D()) model.add(Dense(1, activation = "sigmoid")) とかでどうでしょう.Flatten()よりはGlobalAveragePoolingの方がメモリ食わなくて済むと思います.
KYuki1218

2023/02/06 15:55

name 'AveragePooling1D' is not definedという出力が出たのですが,どんな記載を追加すればよろしいでしょうか。
PondVillege

2023/02/06 15:56

from keras.layers import AveragePooling1D, GlobalAveragePooling1D ですね.
KYuki1218

2023/02/06 15:58

ありがとうございます!今度はmodel.add(Conv1D(4, 128, activation = "swish", kernel_initializer = "he_uniform"))の部分で”One of the dimensions in the output is <= 0 due to downsampling in conv1d_15. Consider increasing the input size. Received input shape [None, 76, 8] which would produce output shape with a zero or negative value in a dimension.”というエラーになりました。
PondVillege

2023/02/06 16:13

すみません,数字が逆でした model = Sequential() model.add(Input(shape = x_train.shape[1:])) model.add(Conv1D(64, 8, activation = "swish", kernel_initializer = "he_uniform")) model.add(AveragePooling1D()) model.add(Conv1D(128, 4, activation = "swish", kernel_initializer = "he_uniform")) model.add(AveragePooling1D()) model.add(Conv1D(256, 3, activation = "swish", kernel_initializer = "he_uniform")) model.add(GlobalAveragePooling1D()) model.add(Dense(1, activation = "sigmoid")) にしてください.
KYuki1218

2023/02/06 16:34

細部に至るまで本当に頭が下がる思いです。 下記のような出力がされたのですが,どこかコードに問題があるのでしょうか。それとも使用しているデータに問題があるのでしょうか。 TN 200/FP 0/FN 200/TP 0 正解率:50.0% Precision: 0.0 Recall: 0.0 F1 score: 0.0 Classification report /usr/local/lib/python3.8/dist-packages/sklearn/metrics/_classification.py:1318: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 due to no predicted samples. Use `zero_division` parameter to control this behavior. _warn_prf(average, modifier, msg_start, len(result))
PondVillege

2023/02/06 16:54 編集

モデルの性能が上がりすぎて過学習したみたいですね,全てNegativeと予測したので,PrecisionやRecallの計算で0除算が起きた.というWarningです. normal:abnormalが46:120,そこから教師データを抜き出して26:100の状態からではバランスが悪く,全部Negativeって出せば精度良くなるんじゃね?という発想のもと学習が進んだものと思われます.(imbalanced dataで調べてください) 一番簡単な方法で解決するとしたら,model.fit()の引数に class_weight = {0: 4, 1: 1} を追加することでしょう.26:100は約1:4なので,重要度としてこれの逆の4:1を辞書型で与える感じです. これでもうまくいくことは少ないので,ここからは,CSVデータを全部扱えるようにしたり,特徴量エンジニアリングを頑張ったり,モデルをいじったり,もっとデータを集めるなど自身で手を動かして検証及び実験しまくるフェーズになります. あと列数が89列と奇数なのが気になります.もしidxが含まれているなら省いたほうがいいと思います.コードの12行目を _x.append([float(col) for col in row[1:]]) にして省けると思います.
KYuki1218

2023/02/06 16:53

非常に勉強になります。imbalanced dataやその周辺の知識について知らないことばかりだと,勉強不足を感じますね… 下記のような記述で問題ないでしょうか。 model.fit( x_train, y_train, batch_size = 8, epochs = 50, class_weight = {0: 4, 1: 1}, validation_data = (x_valid, y_valid) )
PondVillege

2023/02/06 17:42 編集

はい,それで問題ありません. あと1つ重大なことを忘れていました.データの正規化です. ニューラルネットに食わせるデータはなるべく0近傍の値である必要があります. 今の所,座標値が3桁にもなる巨大な数値なので,うまく動作していない可能性が高いです. 普通,min-max normalizationを利用して値域を[0, 1]や[-1, 1]にしたり,Z-score normalizationを利用して分散1,平均0にしたりするような正規化を行います. sklearn.preprocessingにMinMaxScalerやStandardScalerがあるので,これを利用して正規化を行ってください.どの正規化を選ぶかはもちろん,1サンプルごとの値を参照して正規化(sample-wise normalization)するのか,1列ごとの値を参照して正規化(feature-wise normalization)するのか,全てのデータの値を参照して正規化(dataset-wise normalization)するのか,方法は多岐に渡ります.どれが良いのかこちらからはわからないので,いろいろ試してください.Mediapipeならsample-wise normalizationが効果的だと思います. from sklearn.preprocessing import StandardScaler をした上で,19行目 x.append(_x[r: r + roll]) を x.append(StandardScaler().fit_transform(_x[r: r + roll].reshape(-1, 1)).reshape(_x[r: r + roll].shape)) としてみてください.
jbpb0

2023/02/06 23:12 編集

質問者さん 正規化や標準化に付いては、これも見ておくといいと思います https://teratail.com/questions/218412 この質問の範疇外ですが、今後必要になるかもしれませんので
KYuki1218

2023/02/07 09:59

ps_aux_grep様,jbpb0様 昨日から具体的にご指導いただき本当にありがとうございます。 仕事の休憩時間にimbalanced dataや正規化について自己学習してみて,現在していることの意味のわかる部分が少し増えた気がします。 ご教示いただいたsample-wise normalizationで出力したところ,TN 200/FN 200という現象から脱却はできましたが,まだまだ改善の余地のある結果となりました。 TN 180/FP 20/FN 150/TP 50 正解率:57.49999999999999% Precision: 0.7142857142857143 Recall: 0.25 F1 score: 0.37037037037037035 89(列)データのうち下肢の情報は18列であり,上肢や頭部・体幹のデータは削除しても良いのではないかと個人的には思っております(歩行の識別には関係ないのでは)。その場合,コードの12行目を_x.append([float(col) for col in row[1:19]])としても問題ないでしょうか(下肢のデータは1列目から18列目まで)。
PondVillege

2023/02/07 15:45

正解率改善になってよかったです. 18列指定であれば,それで問題ないです.
KYuki1218

2023/02/09 10:14

ps_aux_grep様をはじめ,jbpb0様のおかげで,順調に正解率が高まり,18変数(下肢情報)に絞って実行したところ正解率:62.5%になりました。心から感謝申し上げます。 以前,精度を高めるための方法として,①CSVデータを全部扱えるようにする/②特徴量エンジニアリングを頑張る/③モデルをいじる/④もっとデータを集めるというご助言をいただきましたが,もっとデータを集める以外で何点かご質問がございます。ご多忙中大変恐縮ですが,差し支えなければご回答いただけますと幸いです。 (1)RAMがクラッシュするため,for r in range(len(_x) - roll):をfor r in range(n):に変更しておりましたが,18変数にしたうえで,for r in range(len(_x) - roll):に戻したところ, RAMがクラッシュすることなく実行できました。この処理はCSVデータを全部扱えるようにしていると解釈してもよろしいでしょうか。 (2)特徴エンジニアリングとは,現在の変数を減らしたり(例えば,股関節の情報を残して膝関節の情報を減らすなど),3つのマーカー情報から角度情報を追加するといった内容で間違えないでしょうか。 (3)モデルをいじるというのは, model.addやbatch_size = 8,epochs = 50の部分を変えれば良いでしょうか。 (4)(3)で挙げた部分を調整する場合,何かTipsみたいなものがあればご教示いただけますと嬉しいです。 (5)現在,ホールドアウト検証を使用していると思いますが(間違っていたらすみません…),K-分割交差検証にする場合は,25行目をどのように修正するとよろしいでしょうか。
PondVillege

2023/02/09 12:45 編集

(1): 全ての時間について扱えています. (2): それで間違い無いです.3つのマーカー情報から角度を追加するのが特に良さそうなアプローチですね. (3): モデルをいじるというのは, model.add()で新たなレイヤを追加したり,例えば右足と左足で別のCNNを構築し,特徴量抽出後のレイヤで結合するようにしたりなどが挙げられます.後者の場合はodel.add()スタイル(Sequential API)ではなくFunctional APIを使うことで実現できます(後で回答に書いてみます).batch_sizeとかepochとかもある意味モデルをいじっていますが,効果は少ないでしょう. (4): epochなんかは特に,EaryStoppingで打ち切るのが普通で,自動で調整することになるのが一般的です. (5): 現状のホールドアウト検証をK-分割交差検証に修正するには,trainとtestに分ける(29-34行目)の箇所を重点的に修正することになります. 取り急ぎ回答までにしておきます,あとで解答欄にコードまとめて記述しますので,可能であればここでのやり取りで修正した現状のコードを載せていただけると助かります.
KYuki1218

2023/02/09 12:40

ps_aux_grep様 いつも迅速かつ丁寧にご指導いただきありがとうございます。 初めて機械学習に臨んでいるため分からないことが多い中で,具体的にご教示いただき本当に助かっております。分からない用語もまだまだ多いため,調べながら引き続き続けて参ります。 現状(修正後)のコードに変更しました。ご確認いただけますと幸いです。
PondVillege

2023/02/09 12:57

追記確認しました.いくつか質問があります. 1. CSVファイルの行数のばらつきですが,どのぐらいの幅あるのでしょうか? 2. 健常者と障害者を分類するのには,どのぐらいの行数(時間長,コードで言うroll)が必要でしょうか? 3. 今回rollの長さ分だけ1部分切り抜いて分類を行っていますが,CSVに存在している最低行数と比較してどのぐらい差がありますでしょうか.
KYuki1218

2023/02/09 13:52

1・3. ビデオ(30fps)で撮影したものをmediapipeで解析しており,一番短いものだと7.91秒(237行前後),一番長いものだと192.4秒(5772行前後)ございます。平均して36.0秒(1080行前後),標準偏差は32.9秒(980行前後)と非常にばらつきが大きい状況です。 2. 歩行におけるある現象を捉えたいので,動画にその現象が1〜2秒程度あれば,正常と異常の区別が専門家では可能かと思われます。 お答えになっておりませんでしたら,申し訳ございません…
jbpb0

2023/02/09 14:34

> 動画にその現象が1〜2秒程度あれば,正常と異常の区別が専門家では可能 「その現象を1〜2秒」撮影するには、何秒撮影すればいいのでしょうか? 「その現象」は、どれくらい頻繁に起きるのでしょうか?
PondVillege

2023/02/09 14:46

その情報で大丈夫です. 普通1Epochとは,すべてのデータを使い切った状態を指すのですが,ファイル長も異なる上にサンプル数も少ないことから,最低長に合わせてCSVデータの中身すべてを拡張しながら使うようにしてしまっています. すなわち,1epochとは言いつつもそれ以上の情報を利用しています. この操作で不均衡さが増していないか心配なので,正しく1epochを与えるために,1つのファイルから1つのデータのみ抜き出すように変更しようと思います(一番長いもcsvでも1epochにつき7秒程度の情報しか使わないようにする).歩容がどの7秒弱でも分類可能であると仮定して成り立つ処理であることに注意してください.上述のjbpb0さんの疑問に対する回答次第ではこの仮定を破ることになりますね. これを実現するように目指せばジェネレータを作ることになり,オンラインDAを定義しやすくなり,元々の89列を使った学習が可能になるので,(私の後学のためにも)作ってみます.
KYuki1218

2023/02/09 14:52

jbpb0様,前後が分かれば良いので1〜2秒であれば5秒程度の撮影で問題ないです。歩行中に急に止まってしまったり,歩幅が狭くなる現象であり,患者さんにも寄りますが歩行課題中に1回,多い人だと3回程度生じます。
KYuki1218

2023/02/09 14:58

ps_aux_grep様,細部に至るまでご説明いただきありがとうございます。イメージとしては,野球などで生じるイップスみたいな現象があるかどうかを,動画から分類するというものに近いかもしれません。
jbpb0

2023/02/09 15:10

5秒間に確実に一回はabnormalに特徴的な動作が含まれるのであれば、全てのcsvファイルの先頭の7秒間分だけ使うので、分類できそうですね
PondVillege

2023/02/09 19:35 編集

というわけで,ファイルの先頭どころか画像処理でよく言われるところのRandomCropを46-47行目で実現しておきました(むしろ従来のやつが変ではある).
KYuki1218

2023/02/10 09:18

ps_aux_grep様,本当にいつもありがとうございます! ご教示いただいたコードを元に実行してみます。取り急ぎ,御礼とさせていただきます。
KYuki1218

2023/02/10 09:59

下記のようなエラーが表示されました。どのように修正すればよろしいでしょうか。 InvalidArgumentError Traceback (most recent call last) <ipython-input-2-a162fc71651f> in <module> 130 ) 131 # 学習モデルにデータを与えて学習させる --> 132 model.fit( 133 train_gen, 134 epochs = epochs,
PondVillege

2023/02/10 10:39

すみません,それだけではエラーの原因が不明ですので,エラー全文を質問に追記願います.
KYuki1218

2023/02/10 10:48

お手数おかけして申し訳ございません。 下記の情報でよろしいでしょうか。 -------------------------------------------------------------------------- InvalidArgumentError Traceback (most recent call last) <ipython-input-2-a162fc71651f> in <module> 130 ) 131 # 学習モデルにデータを与えて学習させる --> 132 model.fit( 133 train_gen, 134 epochs = epochs, 1 frames /usr/local/lib/python3.8/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name) 52 try: 53 ctx.ensure_initialized() ---> 54 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name, 55 inputs, attrs, num_outputs) 56 except core._NotOkStatusException as e: InvalidArgumentError: Graph execution error: Detected at node 'model/conv1d_2/Conv1D' defined at (most recent call last): File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.8/dist-packages/ipykernel_launcher.py", line 16, in <module> app.launch_new_instance() File "/usr/local/lib/python3.8/dist-packages/traitlets/config/application.py", line 992, in launch_instance app.start() File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelapp.py", line 612, in start self.io_loop.start() File "/usr/local/lib/python3.8/dist-packages/tornado/platform/asyncio.py", line 149, in start self.asyncio_loop.run_forever() File "/usr/lib/python3.8/asyncio/base_events.py", line 570, in run_forever self._run_once() File "/usr/lib/python3.8/asyncio/base_events.py", line 1859, in _run_once handle._run() File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run self._context.run(self._callback, *self._args) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 690, in <lambda> lambda f: self._run_callback(functools.partial(callback, future)) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 743, in _run_callback ret = callback() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 787, in inner self.run() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 748, in run yielded = self.gen.send(value) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 365, in process_one yield gen.maybe_future(dispatch(*args)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 268, in dispatch_shell yield gen.maybe_future(handler(stream, idents, msg)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 543, in execute_request self.do_execute( File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/ipkernel.py", line 306, in do_execute res = shell.run_cell(code, store_history=store_history, silent=silent) File "/usr/local/lib/python3.8/dist-packages/ipykernel/zmqshell.py", line 536, in run_cell return super(ZMQInteractiveShell, self).run_cell(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2854, in run_cell result = self._run_cell( File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2881, in _run_cell return runner(coro) File "/usr/local/lib/python3.8/dist-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner coro.send(None) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3057, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3249, in run_ast_nodes if (await self.run_code(code, result, async_=asy)): File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3326, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-2-a162fc71651f>", line 132, in <module> model.fit( File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 64, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1409, in fit tmp_logs = self.train_function(iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1051, in train_function return step_function(self, iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1040, in step_function outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1030, in run_step outputs = model.train_step(data) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 889, in train_step y_pred = self(x, training=True) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 64, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 490, in __call__ return super().__call__(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 64, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1014, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 92, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 458, in call return self._run_internal_graph( File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 596, in _run_internal_graph outputs = node.layer(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 64, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1014, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 92, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 250, in call outputs = self.convolution_op(inputs, self.kernel) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 225, in convolution_op return tf.nn.convolution( Node: 'model/conv1d_2/Conv1D' input depth must be evenly divisible by filter depth: 83 vs 12 [[{{node model/conv1d_2/Conv1D}}]] [Op:__inference_train_function_2873]
PondVillege

2023/02/10 11:01

なるほど,18列に絞って与えるのではなく,元の89列のデータを与えたのですね.18列に絞ったとのことでしたので,generate_pseudo_data()では18列のみを生成しました.伝わりづらくて申し訳ありません. それを踏まえて18列しかないCSVに対して49-51行目で X1.append(data[:, :3]) X2.append(data[:, 3:6]) X3.append(data[:, 6:]) と書くことで,それぞれX1,X2が3列,X3が12列のデータを保持することになっていました. またこの列数の指定はモデルの78-80行目で inputs1 = Input(shape = (time_stamp, 3)) inputs2 = Input(shape = (time_stamp, 3)) inputs3 = Input(shape = (time_stamp, 12)) と定義しています.特に今回は89列のデータが元データなので例えば X1.append(data[:, 8:11]) X2.append(data[:, 11:14]) X3.append(data[:, 14:26]) とすれば,X1,X2で3列,X3で12列扱うことになります.ここら辺はmediapipeの吐き出すCSVフォーマットに従って好きなように書き換えてください.
KYuki1218

2023/02/10 11:56

私の知識不足でお手数おかけして申し訳ございません。 ご教示いただいたコードで実行したところ,下記の結果となりました。 TN 0 / FP 15 / FN 2 / TP 38 正解率:69.0909090909091% Precision: 0.7169811320754716 Recall: 0.95 F1 score: 0.8172043010752688 ・X1.append(data[:, 8:11])というのは,8列目から11列目の変数を指定していることを意味しているのでしょうか。
PondVillege

2023/02/10 14:09 編集

なるほど,TNが0なのに正解率が高く見えてしまっているので,balanced_accuracy_scoreを使った方が良さそうですね. > X1.append(data[:, 8:11])というのは,8列目から11列目の変数を指定していることを意味しているのでしょうか。 左様でございます.自由に調整なさってください.3つに分けている現状も真似する必要はありません(興味本位でやりました)ので,mediapipeのデータに対して使われるモデルを調査なさって,反映させるのも良いと思います.
KYuki1218

2023/02/10 15:40

ご教示いただきありがとうございます。 156行をscore = accuracy_score(y_valid, y_pred)に変更するのが良いということでしょうか。 上肢/下肢/体幹で分割すると良いのではと考えたため,それで試してみます。 また,何度もご助力いただいて申し訳ないため,今後は私の方で可能な範囲でTrial and Errorを試してみます。その際にTrial and Errorすべき点(データを増やす,特徴エンジニアリング以外に)は下記のような認識でよろしいでしょうか。 ・49-51行目の読み込むべき変数を変える ・88/90/92行目をmodel.add(LSTM())を変更する(その場合,Conv1D(32, 8…)のような32や8などの数値をどのように決定すれば良いか教えてください)
PondVillege

2023/02/10 19:35 編集

156行目はbalanced_accuracy_scoreですね.上肢/下肢/体幹も良いアイデアだと思います. モデルの変更は,その2つの認識で間違いありません. LSTMの例は回答に追記します.特性上,CNNと比較して実行時間がかかるので注意してください. LSTMで弄るべきは,第一引数のunitsとDropout率ぐらいしか無いです.unitsはDenseのunitsと同義で,LSTMモジュール内に4つのDenseがある形になっています.詳説は次のリンクを参考にしてください. https://www.kaggle.com/code/kmkarakaya/lstm-understanding-the-number-of-parameters 表現力の高さに直結しますので,入力側でLSTMを使う場合は入力の列数より多く持っておくべきですし,出力側でLSTMを使う場合は次元削減の動作を要求することになるので,総合の列数より小さい値を入れることになるでしょう.「LSTM hyper parameters best practices」とかでググるとこの数字が良いよ!ってのがめちゃくちゃ出てきます.が,その数字に固執ことなくチューニングを行う心も大事です.
KYuki1218

2023/02/13 00:12

ps_aux_grep様,ご返信が遅くなってしまい申し訳ございません。いつも有益な情報をいただきありがとうございます。 土日にLSTMを試してみたのですが(ご迷惑かけないように…),結局どこのコードを変えても上手くいかない状況です。(1)具体的な修正方法をご教示いただけますと幸いです。また,調べてみると,(2)CNN-LSTMモデルというのもあるようですが,今回の場合は上手くいきそうでしょうか。もし上手くいきそうであれば,CNN-LSTMモデルのコードをご教示いただけますと幸いです。何度も申し訳ございません…
PondVillege

2023/02/14 11:48

CNN-LSTMモデルはbuild_model2が該当します.他に思い当たる簡単なモデルはResidual ConnectのあるResNetのスタイルを回答に追記しておきます.
KYuki1218

2023/02/14 13:39

いつもご丁寧にご教示いただき本当にありがとうございます。 77-106行を,LSTMの場合はmodel1に,CNN-LSTMの場合はmodel2に,Resnetの場合は別回答の記載にすればよろしいでしょうか。
PondVillege

2023/02/14 15:37

そうですね,色々試してみてください
KYuki1218

2023/02/15 09:38

ご回答ありがとうございます。各モデルともエラーが出てしまいます…どこを修正すればよろしいでしょうか。 ■LSTM(model1) ValueError Traceback (most recent call last) <ipython-input-2-ad3335173332> in <module> 118 test_generator = generator.generator(generator.test_idx, 1) 119 for (X1, X2, X3), y in test_generator: --> 120 y_pred.extend(np.round(model.predict([X1, X2, X3], batch_size = batch_size))) 121 y_valid.extend(y) 122 1 frames /usr/local/lib/python3.8/dist-packages/keras/engine/training.py in tf__predict_function(iterator) 13 try: 14 do_return = True ---> 15 retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope) 16 except: 17 do_return = False ValueError: in user code: File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 2137, in predict_function * return step_function(self, iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 2123, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 2111, in run_step ** outputs = model.predict_step(data) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 2079, in predict_step return self(x, training=False) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 70, in error_handler raise e.with_traceback(filtered_tb) from None File "/usr/local/lib/python3.8/dist-packages/keras/engine/input_spec.py", line 295, in assert_input_compatibility raise ValueError( ValueError: Input 0 of layer "model" is incompatible with the layer: expected shape=(None, 215, 3), found shape=(8, 215, 6)
KYuki1218

2023/02/15 09:39

■CNN-LSTM(model2) --------------------------------------------------------------------------- NotFoundError Traceback (most recent call last) <ipython-input-2-97ccf0619af6> in <module> 105 ) 106 # 学習モデルにデータを与えて学習させる --> 107 model.fit( 108 train_gen, 109 epochs = epochs, 1 frames /usr/local/lib/python3.8/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name) 50 try: 51 ctx.ensure_initialized() ---> 52 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name, 53 inputs, attrs, num_outputs) 54 except core._NotOkStatusException as e: NotFoundError: Graph execution error: Detected at node 'model_1/conv1d_4/Conv1D' defined at (most recent call last): File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.8/dist-packages/ipykernel_launcher.py", line 16, in <module> app.launch_new_instance() File "/usr/local/lib/python3.8/dist-packages/traitlets/config/application.py", line 992, in launch_instance app.start() File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelapp.py", line 612, in start self.io_loop.start() File "/usr/local/lib/python3.8/dist-packages/tornado/platform/asyncio.py", line 149, in start self.asyncio_loop.run_forever() File "/usr/lib/python3.8/asyncio/base_events.py", line 570, in run_forever self._run_once() File "/usr/lib/python3.8/asyncio/base_events.py", line 1859, in _run_once handle._run() File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run self._context.run(self._callback, *self._args) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 690, in <lambda> lambda f: self._run_callback(functools.partial(callback, future)) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 743, in _run_callback ret = callback() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 787, in inner self.run() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 748, in run yielded = self.gen.send(value) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 365, in process_one yield gen.maybe_future(dispatch(*args)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 268, in dispatch_shell yield gen.maybe_future(handler(stream, idents, msg)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 543, in execute_request self.do_execute( File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/ipkernel.py", line 306, in do_execute res = shell.run_cell(code, store_history=store_history, silent=silent) File "/usr/local/lib/python3.8/dist-packages/ipykernel/zmqshell.py", line 536, in run_cell return super(ZMQInteractiveShell, self).run_cell(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2854, in run_cell result = self._run_cell( File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2881, in _run_cell return runner(coro) File "/usr/local/lib/python3.8/dist-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner coro.send(None) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3057, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3249, in run_ast_nodes if (await self.run_code(code, result, async_=asy)): File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3326, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-2-97ccf0619af6>", line 107, in <module> model.fit( File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1650, in fit tmp_logs = self.train_function(iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1249, in train_function return step_function(self, iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1233, in step_function outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1222, in run_step outputs = model.train_step(data) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1023, in train_step y_pred = self(x, training=True) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 561, in __call__ return super().__call__(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1132, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 96, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 511, in call return self._run_internal_graph(inputs, training=training, mask=mask) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 668, in _run_internal_graph outputs = node.layer(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1132, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 96, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 283, in call outputs = self.convolution_op(inputs, self.kernel) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 255, in convolution_op return tf.nn.convolution( Node: 'model_1/conv1d_4/Conv1D' No algorithm worked! Error messages: [[{{node model_1/conv1d_4/Conv1D}}]] [Op:__inference_train_function_7603]
KYuki1218

2023/02/15 09:40

■ResNetのスタイル --------------------------------------------------------------------------- InvalidArgumentError Traceback (most recent call last) <ipython-input-1-9d6932b71a6d> in <module> 132 ) 133 # 学習モデルにデータを与えて学習させる --> 134 model.fit( 135 train_gen, 136 epochs = epochs, 1 frames /usr/local/lib/python3.8/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name) 50 try: 51 ctx.ensure_initialized() ---> 52 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name, 53 inputs, attrs, num_outputs) 54 except core._NotOkStatusException as e: InvalidArgumentError: Graph execution error: Detected at node 'model/conv1d/Conv1D' defined at (most recent call last): File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.8/dist-packages/ipykernel_launcher.py", line 16, in <module> app.launch_new_instance() File "/usr/local/lib/python3.8/dist-packages/traitlets/config/application.py", line 992, in launch_instance app.start() File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelapp.py", line 612, in start self.io_loop.start() File "/usr/local/lib/python3.8/dist-packages/tornado/platform/asyncio.py", line 149, in start self.asyncio_loop.run_forever() File "/usr/lib/python3.8/asyncio/base_events.py", line 570, in run_forever self._run_once() File "/usr/lib/python3.8/asyncio/base_events.py", line 1859, in _run_once handle._run() File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run self._context.run(self._callback, *self._args) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 690, in <lambda> lambda f: self._run_callback(functools.partial(callback, future)) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 743, in _run_callback ret = callback() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 787, in inner self.run() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 748, in run yielded = self.gen.send(value) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 365, in process_one yield gen.maybe_future(dispatch(*args)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 268, in dispatch_shell yield gen.maybe_future(handler(stream, idents, msg)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 543, in execute_request self.do_execute( File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/ipkernel.py", line 306, in do_execute res = shell.run_cell(code, store_history=store_history, silent=silent) File "/usr/local/lib/python3.8/dist-packages/ipykernel/zmqshell.py", line 536, in run_cell return super(ZMQInteractiveShell, self).run_cell(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2854, in run_cell result = self._run_cell( File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2881, in _run_cell return runner(coro) File "/usr/local/lib/python3.8/dist-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner coro.send(None) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3057, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3249, in run_ast_nodes if (await self.run_code(code, result, async_=asy)): File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3326, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-1-9d6932b71a6d>", line 134, in <module> model.fit( File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1650, in fit tmp_logs = self.train_function(iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1249, in train_function return step_function(self, iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1233, in step_function outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1222, in run_step outputs = model.train_step(data) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1023, in train_step y_pred = self(x, training=True) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 561, in __call__ return super().__call__(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1132, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 96, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 511, in call return self._run_internal_graph(inputs, training=training, mask=mask) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 668, in _run_internal_graph outputs = node.layer(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1132, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 96, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 283, in call outputs = self.convolution_op(inputs, self.kernel) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 255, in convolution_op return tf.nn.convolution( Node: 'model/conv1d/Conv1D' input depth must be evenly divisible by filter depth: 42 vs 18 [[{{node model/conv1d/Conv1D}}]] [Op:__inference_train_function_10555]
PondVillege

2023/02/16 13:13 編集

model1 inputs1 = Input(shape = (215, 6)) にしたら治ると思います.例示コードの49行目のX1と同等の形状を与えてください. 正しくは,yieldで返す2要素tupleの0番目に与える配列の形状と同等にしてください. とはいうものの,trainは動いてtestの段階で形状が違うのはよくわかりません.CSVがおかしかったりするかもです. model2 はじめてみたエラーです. https://zenn.dev/aquahika/articles/61da9970f532cd 参考になれば幸いです. ResNet これはmodel1同様,Input()に指定する形状とDataLoaderで構成したデータの形状違いだと思われます. Google Colabで実行されてるとのことでしたが,モデルごとにNotebookを作るなり,DataLoaderは.pyファイルに切り分けるなり,コードの修正ごとにすべてのセルを実行するなど適切に管理しなければ出会うことのないエラーに直面しがちです.
KYuki1218

2023/02/16 14:45

ご教示いただいた方法で,model1及びResNetは解決いたしました! ただmodel2に関しては,URLに記載している5行のコードを先頭に追加しても改善しませんでした…。他にはどんなことが考えられますでしょうか。なお,モデルごとにnotebookを作成してもmodel2はダメでした。 以下,エラーメッセージになります。 --------------------------------------------------------------------------- NotFoundError Traceback (most recent call last) <ipython-input-5-97ccf0619af6> in <module> 105 ) 106 # 学習モデルにデータを与えて学習させる --> 107 model.fit( 108 train_gen, 109 epochs = epochs, 1 frames /usr/local/lib/python3.8/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name) 50 try: 51 ctx.ensure_initialized() ---> 52 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name, 53 inputs, attrs, num_outputs) 54 except core._NotOkStatusException as e: NotFoundError: Graph execution error: Detected at node 'model_3/conv1d_10/Conv1D' defined at (most recent call last): File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.8/dist-packages/ipykernel_launcher.py", line 16, in <module> app.launch_new_instance() File "/usr/local/lib/python3.8/dist-packages/traitlets/config/application.py", line 992, in launch_instance app.start() File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelapp.py", line 612, in start self.io_loop.start() File "/usr/local/lib/python3.8/dist-packages/tornado/platform/asyncio.py", line 149, in start self.asyncio_loop.run_forever() File "/usr/lib/python3.8/asyncio/base_events.py", line 570, in run_forever self._run_once() File "/usr/lib/python3.8/asyncio/base_events.py", line 1859, in _run_once handle._run() File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run self._context.run(self._callback, *self._args) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 690, in <lambda> lambda f: self._run_callback(functools.partial(callback, future)) File "/usr/local/lib/python3.8/dist-packages/tornado/ioloop.py", line 743, in _run_callback ret = callback() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 787, in inner self.run() File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 748, in run yielded = self.gen.send(value) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 365, in process_one yield gen.maybe_future(dispatch(*args)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 268, in dispatch_shell yield gen.maybe_future(handler(stream, idents, msg)) File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py", line 543, in execute_request self.do_execute( File "/usr/local/lib/python3.8/dist-packages/tornado/gen.py", line 209, in wrapper yielded = next(result) File "/usr/local/lib/python3.8/dist-packages/ipykernel/ipkernel.py", line 306, in do_execute res = shell.run_cell(code, store_history=store_history, silent=silent) File "/usr/local/lib/python3.8/dist-packages/ipykernel/zmqshell.py", line 536, in run_cell return super(ZMQInteractiveShell, self).run_cell(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2854, in run_cell result = self._run_cell( File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 2881, in _run_cell return runner(coro) File "/usr/local/lib/python3.8/dist-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner coro.send(None) File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3057, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3249, in run_ast_nodes if (await self.run_code(code, result, async_=asy)): File "/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py", line 3326, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-5-97ccf0619af6>", line 107, in <module> model.fit( File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1650, in fit tmp_logs = self.train_function(iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1249, in train_function return step_function(self, iterator) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1233, in step_function outputs = model.distribute_strategy.run(run_step, args=(data,)) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1222, in run_step outputs = model.train_step(data) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 1023, in train_step y_pred = self(x, training=True) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/training.py", line 561, in __call__ return super().__call__(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1132, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 96, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 511, in call return self._run_internal_graph(inputs, training=training, mask=mask) File "/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py", line 668, in _run_internal_graph outputs = node.layer(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 65, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/engine/base_layer.py", line 1132, in __call__ outputs = call_fn(inputs, *args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 96, in error_handler return fn(*args, **kwargs) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 283, in call outputs = self.convolution_op(inputs, self.kernel) File "/usr/local/lib/python3.8/dist-packages/keras/layers/convolutional/base_conv.py", line 255, in convolution_op return tf.nn.convolution( Node: 'model_3/conv1d_10/Conv1D' No algorithm worked! Error messages: [[{{node model_3/conv1d_10/Conv1D}}]] [Op:__inference_train_function_15205]
PondVillege

2023/02/17 09:03 編集

ランタイムを「再起動してすべてのセルを実行」とかでも駄目でしょうか. CPUで動作させてみたり,GPUで動作させてみたりして,原因の切り分けをする必要があります. ちなみに,Colabを含むJupyter Notebook系でKerasのモデルを作成するときあるあるなのですが,同一のランタイム上でモデルを作りまくるとconv1d_10みたいにインデックスが割り振られるだけでなく,作成のたびにこのインデックスがどんどん増えてエラーが起きた際にはconv1d_??がどのレイヤを指し示すのかわからなくなります.可能であればランタイム再起動後の初回実行時のエラーを掲載願います.
KYuki1218

2023/02/17 10:32

「再起動してすべてのセルを実行」で解決しました!
KYuki1218

2023/02/17 10:37

ps_aux_grep様,私の無知で経験不足のためご迷惑をおかけしているのも関わらず,懇切丁寧にご助言いただき,本当にありがとうございました!感謝してもしきれません。今後,ご教示いただいたTrial and Errorすべき点を調整しながら,精度の高いモデルとなるように進めて参ります。繰り返しとなりますが,心より感謝申し上げます。
PondVillege

2023/02/17 11:49

手すりとかに捕まってないような,普通の歩容についての解析で,両手および両足の距離を新たな列として挿入,解析するものがあったこと報告しておきます.両手を同時に前後に動かされるとどうしようもないですが,普通は手も足も交互に前後するのでこの距離を手足それぞれで出すと振動する波形が2つできますので,そこから異常を検知できそうですね.よほど変なものを分類しようとしていない限り,この波形のメルスペクトラムを出すだけで異常検知できそうではあります.とはいえ,特徴量エンジニアリングの1アイデアとして試していただければと思います.ぜひ頑張ってください.
KYuki1218

2023/02/18 10:24

貴重な情報をいただき誠にありがとうございます!
KYuki1218

2023/02/20 10:49

ps_aux_grep様,解決済みにした後のご質問で申し訳ございません… 隣合わない変数を選択する場合はどのように記載すればよろしいでしょうか。 例えば,X1にLeft Leg xyzとothersを選択するなど,(素人感覚で大変恐縮ですが…)X1.append(data[:, :3],[:, 6:])のような記載をしてみましたが解決しない状況です。 X1.append(data[:, :3]) # column 0 - 2 is Left Leg xyz ??? X2.append(data[:, 3:6]) # column 3 - 5 is Right Leg xyz ??? X3.append(data[:, 6:]) # others
PondVillege

2023/02/20 11:30

np.concatenate()を利用して次のように書くことができます. N, T, C = 3, 4, 5 x = np.arange(N * T * C).reshape(N, T, C) y = np.arange(N * T * (C + 1)).reshape(N, T, C + 1) print(x.shape, y.shape) # (3, 4, 5), (3, 4, 6) print(np.concatenate([x, y], axis = -1).shape) # (3, 4, 11) 例で言えば X1.append(np.concatenate([data[:, :3], data[:, 6:]], axis = -1)) ですね. このようなデータの形成の段階で結合するのも良いですし,ResNetスタイル22行目でやったようにモデル内で結合することも可能です.
KYuki1218

2023/02/20 12:23

いつも迅速にありがとうございます!解決いたしました。 1回の実行で3回分の結果が出力されますが,X1とX2とX3で選択した変数がそれぞれ出力されている(右足と左足とその他が独立して出力)という認識でよろしいでしょうか(右足と左足とその他の情報が影響し合っていない)。何度も確認してしまい申し訳ございません…
PondVillege

2023/02/20 13:05

> 1回の実行で3回分の結果が出力 02/09 19:14のコメントでホールドアウト検証からK分割交叉検証にされたいとのことでしたので,3分割交叉検証を実装しているので3回分の出力になっています.なのでその認識には誤りがあります.私の説明も不足していました. 基本的に,モデルにはX1,X2,X3すべて入力し最終的には右足と左足とその他の情報が影響し合うようにして予測結果を出すように組んでいます. 特徴抽出器(Feature Extractor)からの情報を分類器(Classifier)に渡すようモデルを形成することをニューラルネットによる予測のセオリーであることを念頭に,解答では分類器には必ずすべての情報を渡すよう組んでいます. https://www.researchgate.net/publication/332750359/figure/fig1/AS:753226571845634@1556594617829/CNN-architecture-showing-the-features-extraction-and-classification-zones-together-with.ppm build_model()ではCNNによる特徴抽出の段階でX1,X2,X3互いの影響を計算しないように組んで,終盤のConcatenateしたあとのDenseで全結合,X1,X2,X3の特徴量を集計(?)して分類を行う.という形にしています.もちろん特徴抽出の段階で互いの影響を計算した方が良いかも知れません. ResNetスタイルではX1,X2,X3と分けていたものを特徴抽出の前で結合しなおして,特徴抽出の段階で相互の影響を扱うようになっています.もちろん特徴抽出の段階で互いの影響を計算すると悪影響があるかもしれません. build_model1()は個別のLSTMで特徴抽出してからX1,X2,X3まとめてLSTM+Denseによる分類を行いますし,build_model2()は個別のCNNで特徴抽出してからX1,X2,X3まとめてLSTM+Denseによる分類を行います.
KYuki1218

2023/02/20 14:40

ご丁寧に回答いただきありがとうございます。 3分割交叉検証のために3回出力されていたのですね(間違った解釈をしておりました…)。 例えば,下肢の情報で分類を行いたい場合は,X1に股関節,X2に膝関節,X3に足関節の変数を入力し,全身の情報で分類したい場合は,X1に頭部,X2に上肢,X3に下肢の変数を入力するといった使用方法になるのでしょうか?
PondVillege

2023/02/20 16:00

はい,そんな感じで良いと思います.うまくいくかはわかりませんが…3つとはいわず5つに増やしたり,座標特徴系と関節間距離特徴系と関節角度系と関節速度系で4つ作ったりとかやりようは無限にあると思います
KYuki1218

2023/03/08 06:49

1) 現在,【TN 13 / FP 3 / FN 14 / TP 19】のように出力されるのですが,分類結果の詳細を出力することは可能でしょうか。また,その判断された推定の信頼度もあると嬉しいです。 下記のようなイメージです(例えば,normal001.csvでは正しく判断され,その信頼度は98%)。 normal001.csv: positive, 0.98 normal002.csv: positive, 0.62 normal003.csv: negative, 0.82 … abnormal001.csv: negative, 0.53 abnormal002.csv: negative, 0.87 2) 推定の信頼度の閾値を変えることは可能でしょうか。可能であれば,Recall(取りこぼしをなくす)が高まるようなモデルにしたいと考えております。 上記の2つが可能であれば,具体的にどのように修正すれば良いかご教示いただけますと幸いです。 何度も申し訳ございません…
jbpb0

2023/03/08 07:54

質問者さん 元々の質問内容と大きく乖離してるので、別の質問にした方がいいと思います
jbpb0

2023/03/08 07:59

> 具体的にどのように修正すれば良いかご教示いただけますと幸いです。 https://teratail.com/help/avoid-asking の「コードをください・デバッグしてください等の丸投げの質問」と、 https://teratail.com/help/question-tips の「1. 質問をする前に心がけてほしいこと」を見てください まずは、自分で調べて、考えて、コードを書きましょう そうした上で、うまくいかないところを質問しましょう
PondVillege

2023/03/08 10:43

model.predict()で得られた信頼度(というより生起確率)をnp.round()で偶数丸めという四捨五入に近い操作をして0か1にしています.ここらへんの操作を改めてください. また,csvファイル名が欲しい場合,ジェネレータを改良する必要があります. 新たに質問を立てる際に参考にしてください.
KYuki1218

2023/03/08 14:46

jbpb0様,建設的なコメントをありがとうございます。回答していただける方に完全に頼ってしまっていたことに反省しております。申し訳ございません。
KYuki1218

2023/03/08 14:50

ps_aux_grep様,本当にいつもありがとうございます。二捨三入や端数処理などのキーワードで調べておりますが,まだ解決策は見当たらない状況です。jbpb0様にコメントいただいている通り,もう少し自分なりに頑張ってみます。
guest

回答2

0

ベストアンサー

質問のエラーの原因

配列形状の違うものをappendしたことで勝手にflattenされる動作によって時系列データになっていなかった.

改善法

サイズの違うCSVから長さを揃えてデータを抽出してappendすること.

python

1import csv 2import math 3import numpy as np 4from glob import glob 5import pandas as pd 6import os 7from sklearn.preprocessing import StandardScaler 8from sklearn.model_selection import StratifiedKFold 9from google.colab import drive 10drive.mount('/content/drive') 11 12#def generate_pseudo_data(): 13# for name, siz in [("normal", 46), ("abnormal", 120)]: 14# for s in range(siz): 15# t = np.linspace(-np.pi, np.pi, np.random.randint(230, 400)) 16# ret = np.array(np.sin(t)) if name == "normal" else np.random.randn(*t.shape) 17# for i in range(17): 18# ret = np.vstack([ret, ret[-1] * np.sin((i + 1) * t + np.pi * i)]) 19# ret = ret.T 20# with open(f"/content/drive/MyDrive/data/{name}/{s}.csv", "w") as f: 21# writer = csv.writer(f) 22# writer.writerow([str(i) for i in range(18)]) 23# writer.writerows([[col for col in row] for row in ret]) 24#generate_pseudo_data() 25 26class DataLoader: 27 def __init__(self, split: int, batch_size: int, epochs: int, roll: int): 28 self.batch_size = batch_size 29 self.epochs = epochs 30 self.roll = roll 31 self.file, self.y, self.l = list(), list(), list() 32 self.category = {"normal": 0, "abnormal": 1} 33 for name in self.category.keys(): 34 for i, file in enumerate(glob(f"/content/drive/MyDrive/data/{name}/*.csv")): 35 self.file.append(file) 36 self.y.append(self.category[name]) 37 self.l.append(len(open(file).readlines()) - 1) # subtract header row 38 assert self.l[-1] > roll, f"Missing roll size: (roll, file length): ({roll}, {self.l[-1]}) on {file}" 39 self.skf = StratifiedKFold(split, shuffle = True) 40 41 def generator(self, idx, epochs): 42 X1, X2, X3, y = list(), list(), list(), list() 43 for e in range(epochs): 44 np.random.shuffle(idx) 45 for i in idx: 46 start = np.random.randint(0, self.l[i] - self.roll - 1) 47 data = pd.read_csv(self.file[i]).values[start: start + self.roll] 48 data = StandardScaler().fit_transform(data.reshape(-1, 1)).reshape(data.shape) 49 X1.append(data[:, :3]) # column 0 - 2 is Left Leg xyz ??? 50 X2.append(data[:, 3:6]) # column 3 - 5 is Right Leg xyz ??? 51 X3.append(data[:, 6:]) # others 52 y.append(self.y[i]) 53 if len(X1) == self.batch_size: 54 yield list(map(np.array, [X1, X2, X3])), np.array(y) # Returning Just one batch 55 X1, X2, X3, y = list(), list(), list(), list() 56 if len(X1): 57 yield list(map(np.array, [X1, X2, X3])), np.array(y) # Rreturning remain batch 58 59 def split(self): 60 for train, test in self.skf.split(self.file, self.y): 61 self.test_idx = test 62 yield ( 63 self.generator(train, self.epochs), 64 self.generator(test, self.epochs), 65 math.ceil(len(train) / self.batch_size), 66 math.ceil(len(test) / self.batch_size) 67 ) 68 69import tensorflow as tf 70from tensorflow.python import keras 71from keras.models import Sequential, Model 72from keras.layers import Input, Dense, Concatenate, Flatten, Dropout 73from keras.layers import Conv1D, AveragePooling1D, GlobalAveragePooling1D 74from keras.optimizers import Adam 75from keras.callbacks import EarlyStopping, ReduceLROnPlateau 76 77def build_model(time_stamp): 78 inputs1 = Input(shape = (time_stamp, 3)) 79 inputs2 = Input(shape = (time_stamp, 3)) 80 inputs3 = Input(shape = (time_stamp, 12)) 81 82 # align channel size for cnn(x) 83 x1 = Conv1D(32, 8, activation = "swish", kernel_initializer = "he_uniform")(inputs1) 84 x2 = Conv1D(32, 8, activation = "swish", kernel_initializer = "he_uniform")(inputs2) 85 x3 = Conv1D(32, 8, activation = "swish", kernel_initializer = "he_uniform")(inputs3) 86 87 cnn_layer = [ 88 Conv1D(64, 3, activation = "swish", kernel_initializer = "he_uniform"), 89 AveragePooling1D(), 90 Conv1D(128, 3, activation = "swish", kernel_initializer = "he_uniform"), 91 AveragePooling1D(), 92 Conv1D(256, 3, activation = "swish", kernel_initializer = "he_uniform"), 93 GlobalAveragePooling1D(), 94 ] 95 def cnn(x): 96 for layer in cnn_layer: 97 x = layer(x) 98 return x 99 100 combined = Concatenate()([cnn(x1), cnn(x2), cnn(x3)]) 101 x = Dropout(0.5)(combined) 102 x = Dense(256, activation = "swish")(x) 103 x = Dropout(0.5)(x) 104 x = Dense(128, activation = "swish")(x) 105 x = Dense(1, activation = "sigmoid")(x) 106 return Model(inputs = [inputs1, inputs2, inputs3], outputs = x) 107 108from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay 109from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score 110 111epochs = 128 112batch_size = 8 113time_stamp = 215 114generator = DataLoader(split = 3, roll = time_stamp, batch_size = batch_size, epochs = epochs) 115 116for train_gen, valid_gen, steps_per_epoch, validation_steps in generator.split(): 117 model = build_model(time_stamp) # Be sure to rebuild the model with each fold. 118 model.summary() 119 model.compile( 120 loss = "binary_crossentropy", 121 optimizer = Adam(), 122 metrics = ["acc"] 123 ) 124 es = EarlyStopping( 125 monitor = "val_loss", # val_lossが 126 patience = 10, # 10epoch間で 127 mode = "min", # 最小値を更新しなかったら 128 restore_best_weights = True, # ベストのweightsを採用して終了 129 verbose = 1, 130 ) 131 # 学習モデルにデータを与えて学習させる 132 model.fit( 133 train_gen, 134 epochs = epochs, 135 steps_per_epoch = steps_per_epoch, 136 class_weight = {0: 4, 1: 1}, 137 validation_data = valid_gen, 138 validation_steps = validation_steps, 139 callbacks = [es], 140 ) 141 142 # テストデータを与えて各データの種類を推測 143 # 0から1の 範囲 で得られるのでroundで 四捨五入して0か1にする 144 # 教師データと同様,1部分のみをとって推論するので,何度か計算してみる価値あり 145 y_valid, y_pred = list(), list() 146 test_generator = generator.generator(generator.test_idx, 1) 147 for (X1, X2, X3), y in test_generator: 148 y_pred.extend(np.round(model.predict([X1, X2, X3], batch_size = batch_size))) 149 y_valid.extend(y) 150 151 #混同行列 152 tn, fp, fn, tp = confusion_matrix(y_valid, y_pred).ravel() #混同行列のそれぞれの結果を取得 153 print(f"TN {tn} / FP {fp} / FN {fn} / TP {tp}") 154 155 #正解率(Accuracy) 156 score = accuracy_score(y_valid, y_pred) 157 print(f"正解率:{score * 100}%") 158 159 #適合率(Precision) 160 print('Precision:', precision_score(y_valid,y_pred)) 161 162 #再現率(Recall) 163 print('Recall:', recall_score(y_valid,y_pred)) 164 165 #F値(F-measure) 166 print('F1 score:', f1_score(y_valid,y_pred)) 167 print("Classification report")
  • StratifiedKFoldを利用することでデータの比率を揃えたままFoldさせる.
  • CNNによるFeature Extractを特徴量ごとにまとめて実行,Classifierに渡す前に結合Concatenationして推論する.
  • EarlyStoppingによって10epoch間でval_lossの最低値更新がない場合は学習終了とする.
  • 各Foldでモデルを保存しないと消えることに注意

49-51行目の操作が質問の14行目に相当します.モデルの改善による精度改善を期待して,特徴量をXYZ座標値でまとめつつX1,X2,X3に分割してモデルに与えることを想定しています.モデル中で好きなように特徴抽出,結合などの演算を行なってください.精度さえ良ければ3つどころかもっと分割しても面白いですし,隣接する接点ごとに分割することもできると思います.また,CNNでなくLSTM等の時系列を扱うモデルを採用してみるのも良いでしょう.過学習を抑制するために,帰納的バイアスに基づいたモデル設計を推奨します.ここらからはTrial and Errorの段階です.

イメージ説明

LSTMを使う例を示します.

python

1from keras.layers import LSTM 2def build_model1(time_stamp): 3 inputs1 = Input(shape = (time_stamp, 3)) 4 inputs2 = Input(shape = (time_stamp, 3)) 5 inputs3 = Input(shape = (time_stamp, 12)) 6 7 x1 = LSTM(32, dropout = 0.2, return_sequences = True)(inputs1) # 3列を32列で表現させる 8 x2 = LSTM(32, dropout = 0.2, return_sequences = True)(inputs2) # 3列を32列で表現させる 9 x3 = LSTM(32, dropout = 0.2, return_sequences = True)(inputs3) # 12列を32列で表現させる 10 11 combined = Concatenate(axis = -1)([x1, x2, x3]) # 32+32+32=96列になる 12 x = LSTM(32, dropout = 0.2)(combined) # 32列に圧縮する 13 x = Dense(1, activation = "sigmoid")(x) 14 return Model(inputs = [inputs1, inputs2, inputs3], outputs = x) 15 16def build_model2(time_stamp): 17 inputs1 = Input(shape = (time_stamp, 3)) 18 inputs2 = Input(shape = (time_stamp, 3)) 19 inputs3 = Input(shape = (time_stamp, 12)) 20 21 x1 = Conv1D(32, 7, activation = "swish", kernel_initializer = "he_uniform")(inputs1) # 3列を32列で表現させる 22 x1 = AveragePooling1D()(x1) # 時間軸上で半分に圧縮する 23 x2 = Conv1D(32, 7, activation = "swish", kernel_initializer = "he_uniform")(inputs2) # 3列を32列で表現させる 24 x2 = AveragePooling1D()(x2) # 時間軸上で半分に圧縮する 25 x3 = Conv1D(32, 7, activation = "swish", kernel_initializer = "he_uniform")(inputs3) # 12列を32列で表現させる 26 x3 = AveragePooling1D()(x3) # 時間軸上で半分に圧縮する 27 28 combined = Concatenate(axis = -1)([x1, x2, x3]) # 32+32+32=96列になる 29 x = LSTM(32, dropout = 0.2)(combined) # 32列に圧縮する 30 x = Dense(1, activation = "sigmoid")(x) 31 return Model(inputs = [inputs1, inputs2, inputs3], outputs = x)

KerasのLSTMについて読んでからパラメータをいじった方が良さそうです.特にcuDNNに対応していないパラメータを利用するとGPUでも遅くなります.一般には,入力側の表現力を大きく,出力側の表現力を小さくするようにパラメータをいじります.ここでは列数が表現力に相当しますね.

投稿2023/02/09 17:26

編集2023/02/10 17:20
PondVillege

総合スコア1579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

文字制限超えたみたいなので別回答に追記します.

ResNetスタイル.ResNet18と同等.

Python

1from keras.layers import BatchNormalization, Activation, Add, Dropout, MaxPooling1D 2def ConvBNAct(filters, kernel_size, activation = "swish"): 3 def apply(inputs): 4 x = Conv1D(filters, kernel_size, padding = "same", kernel_initializer = "he_uniform")(inputs) 5 x = BatchNormalization()(x) 6 x = Activation(activation)(x) 7 return x 8 return apply 9 10def ResBlock(filters, kernel_size): 11 def apply(inputs): 12 x = ConvBNAct(filters, kernel_size)(inputs) 13 x = ConvBNAct(filters, kernel_size)(x) 14 return Add()([x, Conv1D(filters, 1)(inputs)]) 15 return apply 16 17def build_model(time_stamp): 18 inputs1 = Input(shape = (time_stamp, 3)) 19 inputs2 = Input(shape = (time_stamp, 3)) 20 inputs3 = Input(shape = (time_stamp, 12)) 21 22 x = Concatenate(axis = -1)([inputs1, inputs2, inputs3]) 23 x = ResBlock(64, 7)(x) 24 x = MaxPooling1D()(x) 25 x = ResBlock(64, 5)(x) 26 x = ResBlock(64, 3)(x) 27 x = MaxPooling1D()(x) 28 x = ResBlock(128, 3)(x) 29 x = ResBlock(128, 3)(x) 30 x = MaxPooling1D()(x) 31 x = ResBlock(256, 3)(x) 32 x = ResBlock(256, 3)(x) 33 x = MaxPooling1D()(x) 34 x = ResBlock(512, 3)(x) 35 x = ResBlock(512, 3)(x) 36 x = GlobalAveragePooling1D()(x) 37 x = Dropout(0.5)(x) 38 x = Dense(256, activation = "swish")(x) 39 x = Dropout(0.5)(x) 40 x = Dense(64, activation = "swish")(x) 41 x = Dropout(0.5)(x) 42 x = Dense(16, activation = "swish")(x) 43 x = Dense(1, activation = "sigmoid")(x) 44 return Model(inputs = [inputs1, inputs2, inputs3], outputs = x)

投稿2023/02/14 11:53

編集2023/02/14 12:39
PondVillege

総合スコア1579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問