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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Google Colaboratory

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

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

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

Q&A

解決済

1回答

1390閲覧

RandomForestの精度評価を正確に反映させたい

do-shiro-to

総合スコア2

Google Colaboratory

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

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

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

0グッド

0クリップ

投稿2022/11/11 05:48

編集2023/02/16 05:24

前提

時系列データをRandomForestClassifierで分類しようとしています。
先程までは、valueerrorが発生してしまうという質問だったのですが、データ内容を変更した所、エラーは解消されました。
しかし、その後のclf = RandomForestClassifier~~~で行った精度評価に違和感を覚えてしまい、こちらで質問内容を変更させて頂きたく、修正しております。

機械学習は初めて触っており、分からないことばかりなので不十分な質問になってしまっていたら申し訳ございません。
なにかアドバイスを頂ければ幸いです。

追記

実現したいこと

ここに実現したいことを箇条書きで書いてください。

  • RandomForestClassifierを実装した時に、どのデータを使用しても精度が100%になってしまう原因を知り、正確な出力ができるよう対処したい。

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

エラーは出ないのですが、分類の精度評価がデータを変更しても精度評価のスコアが100%になってしまいます。

該当のソースコード

GoogleColaboratory

1import pandas as pd 2from sklearn.model_selection import train_test_split 3from sklearn.ensemble import RandomForestClassifier 4 5df = pd.read_csv("k100xt_v2.csv") 6 7df.shape 8 9df.head() 10 11df = df[(df["t"] == "curve") | (df["t"] == "straight")] 12 13df["t"] = df["t"].replace("straight",0) 14df["t"] = df["t"].replace("curve",1) 15 16df = pd.get_dummies(df,drop_first = True) 17 18train_data = df.drop("x", axis=1) 19y = df["t"].values 20X = train_data.values 21 22X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0) 23 24X_train.shape,X_test.shape,y_train.shape,y_test.shape 25 26clf = RandomForestClassifier(random_state=0) 27clf.fit(X_train, y_train) 28print("score=", clf.score(X_test, y_test)) 29

試したこと

・データの行数を300や700に変更
・random_stateを1234から0や34などランダムに変更

補足情報(FW/ツールのバージョンなど)

以下のサイトを参考にしており、元々使用しているデータと違う為必要の無いコードがある可能性があります。質問文を簡潔に書くことができず、申し訳ございません。
https://qiita.com/Hawaii/items/5831e667723b66b46fba

読み込んだデータは1002行7列の加速度データで線形となっており、文字数の関係上こちらに全文記載することはできませんが、序盤の30行ほどを記載させて頂きます。

x,y,z,re,xt,abs,t
-0.026031,-0.976059,0.119003,0.983631282,0,0.026031,straight
-0.064987,-1.03804,0.12355,1.047384817,0,0.064987,straight
-0.004471,-0.995529,0.139633,1.005283718,0,0.004471,straight
-0.085449,-0.960175,0.097488,0.968886718,0,0.085449,straight
0.035767,-0.907028,0.14296,0.918921451,0,0.035767,straight
-0.011917,-0.894821,0.142151,0.906120049,0,0.011917,straight
0.003983,-0.69928,0.007187,0.699328275,0,0.003983,straight
-0.078888,-0.890335,-0.034653,0.894494583,0,0.078888,straight
0.152542,-0.717941,-0.035721,0.734836261,0,0.152542,straight
-0.061661,-1.015518,-0.035339,1.018001833,0,0.061661,straight
-0.096069,-1.020569,0.138306,1.034368835,0,0.096069,straight
-0.047028,-1.07959,0.099106,1.08514893,0,0.047028,straight
-0.077408,-1.119263,0.169281,1.1346355,0,0.077408,straight
0.121902,-1.052505,0.157715,1.071214681,0,0.121902,straight
0.021805,-1.08139,0.156631,1.092892063,0,0.021805,straight
-0.099991,-0.915634,0.155319,0.934081267,0,0.099991,straight
-0.198471,-1.043808,0.098312,1.067047856,0,0.198471,straight
0.081284,-1.092499,0.100479,1.100116895,0,0.081284,straight
-0.296371,-0.95253,0.216736,1.020844584,0,0.296371,straight
0.122726,-0.81517,0.036789,0.82517709,0,0.122726,straight
-0.082077,-0.774368,-0.265396,0.82268917,0,0.082077,straight
-0.155334,-0.872314,-0.045181,0.887187516,0,0.155334,straight
-0.10614,-1.170898,0.0047,1.175708261,0,0.10614,straight
-0.02742,-1.092712,0.263962,1.12447646,0,0.02742,straight
-0.108902,-1.078354,0.145279,1.093532342,0,0.108902,straight
-0.191116,-0.966019,-0.031448,0.985244645,0,0.191116,straight
-0.052795,-0.955856,-0.029785,0.957776149,0,0.052795,straight
-0.081512,-1.054367,0.057022,1.059049331,0,0.081512,straight
-0.220535,-1.044144,0.092484,1.071179569,0,0.220535,straight

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

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

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

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

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

PondVillege

2022/11/12 04:38 編集

示していただいたデータのtは全てstraightですが,このk100xt_v2.csvの中にcurveはあるのでしょうか? 前回の質問での > 例えば決定木の分岐条件で○軸加速度の値○○以上などで分類して、というのも難しい物なのでしょうか ですが,これが可能なのは構造化データのみだと思った方が良いです.今回の非構造化データに対するランダムフォレストによる分類ではx軸加速度の値が時刻tで〇以上〇以下で かつ y軸加速度の値が時刻t+100で〇以上〇以下みたいな,変な情報抽出をしかねません 例えば次のサイトでは https://www.talend.com/jp/resources/data-mining-techniques/ 複雑なランダムフォレストモデルは、入力を基にして常に簡単に出力を理解できるとは限らないため、ブラックボックス型の機械学習手法と見なされます。 と書かれています.指導教員による指示でホワイトボックスな決定木よりも強力であるランダムフォレストを使わされているなら,ブラックボックスであることを勉強して論破してやった方がいいと思います.もはや単純な全層結合ニューラルネットワークを使うことと何ら変わらないです. 時系列データを扱えるニューラルネットワークで分類した方が筋が通っています もし,直進か右左折となる加速度の条件抽出したいなら線形手法で構成した単純な分類器のハイパーパラメータチューニング(ベイズ最適化とか)による抽出をおすすめします.
bsdfan

2022/11/11 22:45

train_data = df.drop("x", axis=1) X = train_data.values dropするのは t では? X に t 列の値が含まれているので、それで学習すると正解を知っているので、100% になってもおかしくはないですね。
PondVillege

2022/11/12 10:23

そうですね,tの値をそのまま出力したら高精度になる,という学習がおきますね.
do-shiro-to

2022/11/13 06:09 編集

お二方とも、コメント頂き本当にありがとうございます。 ps_aux_grep様、前回に引き続きありがとうございます。前回頂いた回答に問題があった訳ではないのですが、せっかく頂いたアドバイスを活かしきることができず申し訳ございません。 >示していただいたデータのtは全てstraightですが,このk100xt_v2.csvの中にcurveはあるのでしょうか? はい、仰るとおりです。ここではx軸加速度の絶対値absが0.3以上の物をcurveと表示するようにしていました。 >入力を基にして常に簡単に出力を理解できるとは限らないため、ブラックボックス型の機械学習手法 これは、データを分割した時に分割の割合は分かってもその詳しい中身(例えば7:3でデータ分割してもテストデータがどこからどこまで3割を使用したのか)が見えないという解釈でしょうか、それともただ単に最終的に出力された分類の精度が何を基準にどう評価しているかが不明瞭という解釈でしょうか。 >指導教員による指示でホワイトボックスな決定木よりも強力であるランダムフォレストを使わされているなら,ブラックボックスであることを勉強して論破してやった方がいいと思います おそらく私自身の説得する力が足りないためか、卒業がかかっていることもあり発言力g弱い為か、調べきれていないことや機械学習の基礎から勉強が足りていない、必ず1から0で出力できるはずだという理由で強引に調査し直しする事になりました…。特に後者の勉強が足りていないという部分は完全に私が悪いと思っており、そこは必死に一から勉強中です。 >直進か右左折となる加速度の条件抽出したいなら線形手法で構成した単純な分類器のハイパーパラメータチューニング(ベイズ最適化とか)による抽出をおすすめします おすすめを教えて頂きありがとうございます。RandomForestと並行にはなるため遅くはなってしまいますが、試行させて頂きます。 bsdfan様、コメント頂き本当にありがとうございます。 >dropするのは t では? 確かに、訓練データに目標値tが入っていてはいけないと思い、tをdropしたのですがそれでも精度は100%になってしまいました。もしかするとtrain_dataからx軸加速度以外の列を全部dropしてしまった方がよいのでしょうか。
bsdfan

2022/11/13 08:49

過去の質問も見たのですが、データの各点(1行のデータ)毎に直線・カーブを判定したいのか、もしくは何行か塊(シーケンス)に対して直線・カーブを判定したいのか、どちらなのでしょうか? なんとなく後者をやりたいのかと感じたのですが、いまやっているのは前者なので、ちょっと気になりました。
do-shiro-to

2022/11/13 09:52

bsdfan様、過去の質問まで参照して頂きありがとうございます。 >データの各点(1行のデータ)毎に直線・カーブを判定したいのか、もしくは何行か塊(シーケンス)に対して直線・カーブを判定したいのか、どちら 仰るとおりどちらかと言えば後者をやりたいのですが、これまでに頂いた回答や調査から、RandomForestではやりたいことに向いていない可能性が高くなっていること、そもそも機械学習の経験も少なく、片っ端からRandomForestClassifierを試していること、と言う風に手段と目的が反対になってしまっている感が否めないのですが、現状前者をやってしまっているようですね…。紛らわしくて申し訳ありません…。
jbpb0

2022/11/14 08:38

> x軸加速度の絶対値absが0.3以上の物をcurve というルールが簡単すぎて、完全に見破られて、 > どのデータを使用しても精度が100% となってるのではないですかね
do-shiro-to

2022/11/14 15:55

jbpd0様、コメントいただきありがとうございます。 curveになる条件を追加してみたところ、98%と相変わらず正確ではなさそうですが100%からは脱却することができました。アドバイスいただきありがとうございます。
jbpb0

2022/11/15 01:37 編集

> 精度評価に違和感を覚えてしまい > 98%と相変わらず正確ではなさそう 100%とか98%とかが「正確ではない」って、どういう意味でしょうか? ほぼ全数を正解する機械学習モデルが完成したのに、何に不満があるのでしょうか? 普通は、学習に使ったのとは別のデータを用意して、それを学習済みモデルに入力して推論させて、推論結果がどれくらい正解したのかを評価します その方法で100%とか98%とかになったのなら、それは学習された機械学習モデルが(解きたいタスクに対して)優秀だ、ということではないのですか? もし、精度の計算方法に疑念があるのでしたら、推論結果と正解を一つずつ確認してみたらいいと思います 何十個か見てほぼ全部正解してるのなら、実際に100%とか98%とか正解してるのでしょう 【追記】 上記はもちろん、教師データの正解が「本当に正解である」のが大前提ですが、そこは大丈夫なのですよね?
do-shiro-to

2022/11/18 07:47

jbpd0様、私自身の言葉足らずで誤解を生んでしまい申し訳ございません。 正確という言葉では無く、これまでのミスで100%になってしまっていたことから、高すぎる精度に対して不信感を持ってしまっていました。 また、機械学習についてもこれまで経験が無く、こんなに早く高精度な物が出る物なのか、という不安もあり、違和感を覚えてしまっていました。 >教師データの正解が「本当に正解である」のが大前提 教師データの正解に関してですが、この質問を投稿したときに用意していた物はそもそもデータセットの構成に不備があったため、前提以前の問題でした。申し訳ございません。
jbpb0

2022/11/18 10:56

> この質問を投稿したときに用意していた物はそもそもデータセットの構成に不備があった 教師データがちゃんとしてなければ、機械学習は無理です それは、時系列がどうとか、ランダムフォレストがどうとか、そんなことを考える以前の問題です
guest

回答1

0

ベストアンサー

入力を基にして常に簡単に出力を理解できるとは限らないため、ブラックボックス型の機械学習手法

これは、データを分割した時に分割の割合は分かってもその詳しい中身(例えば7:3でデータ分割してもテストデータがどこからどこまで3割を使用したのか)が見えないという解釈でしょうか、それともただ単に最終的に出力された分類の精度が何を基準にどう評価しているかが不明瞭という解釈でしょうか。

後者「出力された分類の精度が何を基準にどう評価しているかが不明瞭」が理由でブラックボックスです.例えば10個の弱学習器の決定木が生成されたとして,これらの投票で出力値が決まるわけですから,データの分類基準は,「弱学習器の複雑さ×弱学習器の個数」だけ存在することになるわけです.入力データxyzに関して1ファイル100計測分ある,というのが前回おっしゃっていたことでもありますし,合計300点以上の計測値が1つの出力(straight or curve)を得るような分類器になりそうなので,これを踏まえるとかなり複雑なRandomForestが完成しそうです.それもブラックボックスと言っても申し分ないほどにです.

たとえホワイトボックスである決定木を利用したとしても今回の非構造化データの問題を解くという課題には不適です.

データの各点(1行のデータ)毎に直線・カーブを判定したいのか、もしくは何行か塊(シーケンス)に対して直線・カーブを判定したいのか、どちら

仰るとおりどちらかと言えば後者
現状前者をやってしまっている

本件に関して,塊に対して分類すべく,前回の回答では次のようなディレクトリ構造を作りました.

Tree

1data 2├── straight 3│ ├── 0.csv 4│ ├── 1.csv 5│ ├── 2.csv 6│ ├── ... 7│ └── 19.csv 8└── curve 9 ├── 0.csv 10 ├── 1.csv 11 ├── 2.csv 12 ├── ... 13 └── 9.csv

一般的に,画像や音声,波形データなどの非構造化データを分類する際には,1データ1ファイル,1カテゴリ1フォルダを原則にデータセットを構築します.今回であれば上記のように1サンプル波形1csv,straightとcurveという2カテゴリで2ファイルに分別しておき,これを読み込むようなコードを書くのが常套手段です.機械学習のライブラリでこの構造を読み込むようなモジュールも存在するぐらいです.

コメントの内容からして1つにまとめてしまっているのは非常に悪手だと考えます.

改善案

一旦,閾値を超えたものをcurveにする.みたいなことは忘れてください.上記ディレクトリ構造になったと考えて分類するコードを無理やりRandomForestで扱えるようにして書き下してみます.CSVの形式は前回のものと同様,x, y, z, resultの4列あるものとします.

RandomForestは2階以上のテンソルを扱えないので,無理矢理1階のテンソルに押し込めて分類させます.

Python

1import numpy as np 2import pandas as pd 3from glob import glob 4import csv 5import os 6 7# ---- データ生成部 先述のようなファイル構造を生成する ---- 8# ---- 質問者はこれに従ったファイル構造でデータをおけば良い ---- 9os.makedirs("./data/straight/", exist_ok = True) 10os.makedirs("./data/curve/", exist_ok = True) 11 12def wave(name, t): 13 if name == "straight": 14 return np.random.randn(4) 15 else: 16 return np.sin(t + np.random.randn(4)) 17 18def make_data(name, n): 19 for file in range(n): 20 with open(f"./data/{name}/{file}.csv", "w") as f: 21 writer = csv.writer(f) 22 writer.writerow(["x", "y", "z", "res"]) 23 for i in range(np.random.randint(100, 200)): # ファイルサイズは不定長でもOK 24 writer.writerow(list(wave(name, i))) 25 26make_data("straight", 20) 27make_data("curve", 10) 28 29# ---- データ生成部終了 ---- 30# ---- 以下本質的な内容 ---- 31 32def data_augmentation(_x, _y, roll): # 最小データ長に合わせてデータを増やせるだけ増やす 33 x, y = list(), list() 34 for r in range(0, len(_x) - roll, 3): 35 x.append(_x[r: r + roll]) 36 y.append(_y) 37 return np.array(x), np.array(y) 38 39def load_data(): # データ読み込み 40 data = {"straight": list(), "curve": list()} 41 category = {"straight": 0, "curve": 1} 42 for name in category.keys(): 43 for i, file in enumerate(glob(f"./data/{name}/*.csv")): 44 data[name].append(pd.read_csv(file).values[:, :3].flatten()) # flattenすることで無理矢理1階のテンソルにする 45 46 # 最小のデータ長min_rowを導出する. 47 min_row = min([x.shape[0] for v in data.values() for x in v]) 48 49 split = 2 # 最初の2ファイルは検証用データにする 50 x_train, y_train, x_valid, y_valid = list(), list(), list(), list() 51 for k, v in data.items(): 52 for i, x in enumerate(v): 53 _x, _y = data_augmentation(x, category[k], int(min_row * 0.9)) 54 if i < split: 55 x_valid.extend(_x) 56 y_valid.extend(_y) 57 else: 58 x_train.extend(_x) 59 y_train.extend(_y) 60 61 return map(np.array, [x_train, y_train, x_valid, y_valid]) 62 63x_train, y_train, x_valid, y_valid = load_data() 64 65from sklearn.ensemble import RandomForestClassifier 66from sklearn.metrics import accuracy_score 67 68# 学習モデルを作成 69model = RandomForestClassifier(n_estimators = 10) # 弱学習器を10個作る. 70 71# 学習モデルにテストデータを与えて学習させる 72model.fit(x_train, y_train) 73 74# テストデータを与えて各データの種類を推測 75y_pred = model.predict(x_valid) 76 77# テストデータのラベルを与えて答え合わせ 78score = accuracy_score(y_valid, y_pred) 79print(f"正解率:{score * 100}%")

前回は2階のテンソルを受け付けることのできるモデルだったので,次のようにデータを渡しました
イメージ説明
しかし今回のRandomForestは1階のテンソルしか受け付けることができないのでxyzを横並びにして
イメージ説明
のようにして扱うことで実現しています.

ただやはりこのデータに対してRandomForestを適用しても,出てくる条件は「x0 > 0.1 かつ y100 < 1.0 または x10 < 0.3 かつ z64 < 0.5」みたいな,時系列的に前後関係を把握できなポンコツForestが出来上がってしまうだけですし投票制なので余計複雑です.

と,いうわけで線型手法で構築した分類器を例示しておきます.ベイズ最適化ライブラリoptunaを利用します.もちろん時系列情報を失わないよう,次元平滑化flattenはしないようにします.

Python

1import numpy as np 2import pandas as pd 3from glob import glob 4 5def data_augmentation(_x, _y, roll): # データを増やす.最小データ長に合わせて増やせるだけ増やす 6 x, y = list(), list() 7 for r in range(len(_x) - roll): # 1つ目のコードとの相違点であることに注意 8 x.append(_x[r: r + roll]) 9 y.append([_y]) # 1つ目のコードとの相違点であることに注意 10 return np.array(x), np.array(y) 11 12def load_data(): # データ読み込み 13 data = {"straight": list(), "curve": list()} 14 category = {"straight": 0, "curve": 1} 15 for name in category.keys(): 16 for i, file in enumerate(glob(f"./data/{name}/*.csv")): 17 data[name].append(pd.read_csv(file).values[:, :3]) # flattenしない 18 19 # 最小のデータ長min_rowを導出する. 20 min_row = min([x.shape[0] for v in data.values() for x in v]) 21 22 split = 2 # 最初の2ファイルは検証用データにする 23 x_train, y_train, x_valid, y_valid = list(), list(), list(), list() 24 for k, v in data.items(): 25 for i, x in enumerate(v): 26 _x, _y = data_augmentation(x, category[k], int(min_row * 0.9)) 27 if i < split: 28 x_valid.extend(_x) 29 y_valid.extend(_y) 30 else: 31 x_train.extend(_x) 32 y_train.extend(_y) 33 34 return map(np.array, [x_train, y_train, x_valid, y_valid]) 35 36x_train, y_train, x_valid, y_valid = load_data() 37 38from sklearn.metrics import accuracy_score 39 40# 学習モデルを作成 41class LinearWaveClassifier: 42 def __init__(self, th = 0.5, max_continue = 10, conv = 10, ax_count = 1): 43 self.th = th # 閾値 44 self.max_continue = max_continue # 閾値の連続超過カウント 45 self.conv = conv # 移動平均をとる長さ 46 self.ax_count = ax_count # xyzの何軸が条件に一致したか 47 48 def __predict(self, x): 49 b = np.ones(self.conv) / self.conv 50 x = np.convolve(x, b, mode = "full") 51 x[x < self.th] = 0 52 x[x >= self.th] = 1 53 # https://maspypy.com/numpy%E9%80%A3%E7%B6%9A%E5%90%8C%E4%B8%80%E5%80%A4%E3%81%AE%E6%95%B0%E3%81%88%E4%B8%8A%E3%81%92-atcoder-abc-129-d 54 tmp = np.arange(len(x)) 55 tmp[x > 0] = 0 56 np.maximum.accumulate(tmp, out = tmp) 57 left = tmp 58 x_reversed = x[::-1] 59 tmp = np.arange(len(x)) 60 tmp[x_reversed > 0] = 0 61 np.maximum.accumulate(tmp, out = tmp) 62 cnt_count = len(x) - tmp[::-1] - left - 2 63 cnt_count[x == 0] = 0 64 return self.max_continue < cnt_count.max() 65 66 def _predict(self, x): 67 ret = 0 68 for i in range(x.shape[1]): 69 ret += self.__predict(x[:, i]) 70 return ret >= self.ax_count 71 72 def predict(self, x): 73 return np.array([self._predict(_x) for _x in x]) 74 75 def fit(self, x, y): 76 import optuna 77 78 def bayes_objective(trial): 79 self.th = trial.suggest_float('th', 0.0001, 1, log = True) # 0.0001から1までの範囲で探索 80 self.max_continue = trial.suggest_int('max_continue', 1, 20) # 1から20の範囲で探索 81 self.conv = trial.suggest_int('conv', 2, 20) # 2から20の範囲で探索 82 #self.ax_count = trial.suggest_int('ax_count', 1, 3) 83 pred = self.predict(x) 84 return accuracy_score(pred, y) 85 86 study = optuna.create_study(direction = 'maximize', sampler = optuna.samplers.TPESampler(seed = 1)) 87 study.optimize(bayes_objective, n_trials = 500) 88 print(f"best_params: {study.best_trial.params}") 89 print(f"best_score : {study.best_trial.value}") 90 self.best_params_ = study.best_trial.params 91 self.th = self.best_params_["th"] 92 self.max_continue = self.best_params_["max_continue"] 93 self.conv = self.best_params_["conv"] 94 95model = LinearWaveClassifier() 96 97# 学習モデルにテストデータを与えて学習させる 98model.fit(x_train, y_train) 99 100# テストデータを与えて各データの種類を推測 101y_pred = model.predict(x_valid) 102 103# テストデータのラベルを与えて答え合わせ 104score = accuracy_score(y_valid, y_pred) 105print(f"正解率:{score * 100}%")

このベイズ最適化により得られる

  • th: 波形に設定する閾値
  • max_continue: 閾値を何度連続で超えたらcurveとするか
  • conv: 波形の移動平均を取る長さ
  • ax_count: xyzの何軸が条件に一致したかをみる(今回は最適化せず1軸固定にする)

は今回の手法で発見できる4つの条件ですね.optunaで予測の最適化を行う例を示しました.今回自作したLinearWaveClassifierと精度とRandomForestClassifierのような複雑なモデルの精度を比較してみると学術研究的で良いでしょう.

とにかく,データセットの構築から道を誤っているようでしたので,そこら辺の勉強から始められると良いかと思います.

モデル評価について

自分でテストデータx_test, `y_test``を作成して与える方法

Python

1model = LinearWaveClassifier() 2 3# 学習モデルにテストデータを与えて学習させる 4model.fit(x_train, y_train) 5 6x_test = np.array([ 7 pd.read_csv("02.csv").values[:, :3], # 任意のcsvファイルを与えまくる 8 pd.read_csv("03.csv").values[:, :3], 9 pd.read_csv("??.csv").values[:, :3], 10 pd.read_csv("??.csv").values[:, :3], 11]) 12 13y_test = np.array([ 14 [1], # 02.csvはカーブデータを計測したものであるから1 15 [0], # 03.csvは直進データを計測したものであるから0 16 [1], # ??.csvはカーブデータを計測したものであるから1 17 [1], # ??.csvはカーブデータを計測したものであるから1 18]) 19 20# テストデータを与えて各データの種類を推測 21y_pred = model.predict(x_test) 22 23# テストデータのラベルを与えて答え合わせ 24score = accuracy_score(y_test, y_pred) 25print(f"正解率:{score * 100}%")

ベタ書きでファイル指定しまくることはできます.全然スマートではないですが,応急的にこのようなことは可能です.

投稿2022/11/14 11:39

編集2022/12/05 09:00
PondVillege

総合スコア1579

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

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

do-shiro-to

2022/11/14 15:56

ps_aux_grep様、いつもお世話になっております。 毎回のことながらここまで丁寧な説明かつ時間を割いてコードを書いていただいてしまい、本当にありがとうございます。 ただ、申し訳ないのですが私の勉強不足故で正直なところ始めのディレクトリ構造の部分からつまずいており、調べて勉強しながら一つ一つ処理させて頂きたく思っております。このディレクトリ構造が、GoogleDrive上で作成してColaboratoryで使用してもいいのかどうか、と言う所から調べるほどです。 以上のことからかなりゆっくりとなってしまうとは思われますが、良くも悪くも結果が出れば必ず報告いたします。ですのでどうか、少しの間この質問はこのまま開いた状態にしておいてもよろしいでしょうか。 もしもteratailの規約的に問題があれば、すぐにでもベストアンサーとして解決済みとさせて頂きます。 重ね重ねにはなりますがps_aux_grep様、本当にありがとうございます。
PondVillege

2022/11/14 23:43

質問は自身の疑問が晴れるまで解決しない状態で大丈夫と思います. > このディレクトリ構造が、GoogleDrive上で作成してColaboratoryで使用してもいいのかどうか 別に構いませんし,なんなら普通に取る手段です.マウントしたフォルダをちゃんと指定したら動くと思います.
do-shiro-to

2022/11/18 07:46

ps_aux_grep様、ありがとうございます。 そう言って頂けて、安心しました。なんとか、解決できるまでこぎ着けられるよう勉強していきます。 >別に構いませんし,なんなら普通に取る手段です. ありがとうございます。少しずつにはなってしまっていますが、進めていきます。
do-shiro-to

2022/11/20 08:03 編集

お世話になっております。do-shiro-toです。 2日前から同じ所でつまずいてしまっており、相談させて頂きたく思いました。 dataが定義されていないとの事だったため、data = の部分を見返して読み込むマウントしたファイルのパスを変えたりも試したのですが、そこは影響しないようで個々以外のパスのコードをいじって複数試したのですがエラーが出ることに変わりはありませんでした。 また、以前からご教示頂いている変数rollへの代入の部分も最小データ長である105を代入したいのですがその位置も間違えてしまっているのか、とも不安になっております。 何かアドバイスがいただければ幸いです。 以下エラーメッセージ ```GoogleColaboratory --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-8-c460853f3698> in <module> 1 # 最小のデータ長min_rowを導出する. 2 min_row = 1e9 ----> 3 for k, v in data.items(): 4 for x in v: 5 min_row = min(min_row, x.shape[0]) NameError: name 'data' is not defined ``` 以下コード ```GoogleColaboratory ## データ生成 import numpy as np import pandas as pd from glob import glob import csv import os os.makedirs("/content/drive/MyDrive/data/straight", exist_ok = True) os.makedirs("/content/drive/MyDrive/data/curve", exist_ok = True) def wave(name, t): if name == "straight": return np.random.randn(4) else: return np.sin(t + np.random.randn(4)) def make_data(name, n): for file in range(n): with open(f"/content/drive/MyDrive/data/curve/k14xyz.csv", "w") as f: writer = csv.writer(f) writer.writerow(["x", "y", "z", "res"]) for i in range(np.random.randint(100, 200)): # ファイルサイズは不定長でもOK writer.writerow(list(wave(name, i))) make_data("straight", 20) make_data("curve", 10) ## 学習モデル def data_augmentation(_x, _y, roll): # 最小データ長に合わせてデータを増やせるだけ増やす x, y = list(), list() for r in range(len(_x) - roll): x.append(_x[r: r + roll]) y.append(_y) return np.array(x), np.array(y) def load_data(): # データ読み込み data = {"straight": list(), "curve": list()} category = {"straight": 0, "curve": 1} for name in category.keys(): for i, file in enumerate(glob(f"/content/drive/MyDrive/data/curve/k14xyz.csv")): data[name].append(pd.read_csv(file).values[:, :3].flatten()) # flattenすることで無理矢理1階のテンソルにする # 最小のデータ長min_rowを導出する. min_row = 1e9 for k, v in data.items(): for x in v: min_row = min(min_row, x.shape[0]) ```
PondVillege

2022/11/20 15:36

dataは関数load_data()内で定義されたものを利用していますが,同じブロック内にありますか? あと,データの保存先ディレクトリをそちらの環境に合わせるとすると, glob(f"/content/drive/MyDrive/data/{name}/*.csv") にしてやるべきかと思います.もちろん,ディレクトリごとに直進とカーブでcsvを分けて配置する必要があります. その場合,make_data()等は不要ですね.
do-shiro-to

2022/11/21 04:22 編集

ps_aux_grep様、ありがとうございます。 >同じブロック内にありますか 一応GoogleDrive上では同じブロックにあると考えていたのですが同じディレクトリ、とは訳が違うのでしょうか。質問本文に編集追記で現状のGoogleDriveの状態を画像で載せたので、お手数ですが見て頂けますと幸いです。 >glob(f"/content/drive/MyDrive/data/{name}/*.csv") この{name}/*と言う部分はstraightやcurveに置き換えて.csvの前に個々のcsvファイルの名前を置く、という解釈でよろしいでしょうか。それともglob(f"/content/drive/MyDrive/data/{name}/*.csv")の{name}の部分はそのままと言う解釈でしょうか。
PondVillege

2022/11/21 12:04 編集

画像を拝見しました.Pythonにおける「ブロック」とは,同一の深さのインデントを用いて表現する「実行範囲」のことです.if文のブロックでは,その条件に一致する際に実行される範囲を示しますし,関数のブロックでは,関数内の処理が記述されることになります. 今回,変数dataは関数load_data()内にあるべき変数であり,これを同一ブロックに記述して欲しく思います. Google Colabで書かれているのであれば,1ブロックを複数セルに分けることは不可能です(添付画像はこれをやってしまっています).1関数1セルとかでも良いと思います.次に例を示しますので,参考にしてください. nameに関しては,f文字列というものを利用して変数が代入されますので,このまま記入してください.同様に,globによって*.csvのアスタリスクはワイルドカードとして認識され,ディレクトリ内のcsvファイル名を一括で取得するために利用するものです.
do-shiro-to

2022/11/21 07:12

ps_aux_grep様、返信頂きありがとうございます。 >Pythonにおける「ブロック」とは,同一の深さのインデントを用いて表現する「実行範囲」のこと ディレクトリとは違う話だったのですね…例示まで詳細に解説して頂き本当に頭が上がりません。参考にさせて頂きます。ありがとうございます。
PondVillege

2022/11/21 08:02 編集

さっき気づいたのですが,そちらのディレクトリ構造は /content/drive/MyDrive/data/{name}/*.csv が正しそうですが /content/drive/MyDrive/Society/data/{name}/*.csv で書いてしまっているので,適宜直してください.
do-shiro-to

2022/11/21 09:20

承知いたしました。 ご丁寧に説明頂き、誠にありがとうございます。
PondVillege

2022/11/21 12:06

指摘いただきありがとうございます.リンクは消しました,配慮いただきありがとうございます. そちらでリンクを管理いただければ大丈夫です.
do-shiro-to

2022/11/21 13:05

確認頂きありがとうございます。 リンクは厳重に管理させて頂きます。
PondVillege

2022/11/21 20:07

申し訳ないことに,論理的に問題がある箇所が判明したので回答を修正しています. 回答下部にある編集時間が記載されているリンクから,修正箇所が確認できますので,転記されたコードは修正したほうが良いと思います. 修正前は,軸情報を無視してデータ拡張を行なっていた箇所を,xyz軸の扱いが正しくなるように変更しました.
do-shiro-to

2022/11/24 11:12

ps_aux_grep様、修正箇所を見つけて修正して下さっただけで無くご丁寧にコメントで教えて頂きありがとうございます。 説明頂いた通り、修正させて頂きます。
do-shiro-to

2022/12/02 22:48

失礼いたします。 現在ベイズ最適化ライブラリの方の分類器を実装しようとしているのですが、教示して頂いたコードを実行しようとするとmodel.fit~~の行を実行使用とすると ModuleNotFoundError: No module named 'optuna' のエラーメッセージが表示されるのですが、これはインポートが上手くいっていない可能性があるのでしょうか。そう思ってimport optuna等のインポート系統のコードをまとめて一番始めに持ってきても同じエラーメッセージが発生してしまいました。 他にもブロックを変えてみたりといった試行をしてみましたが、別のエラーが発生してしまい手が止まってしまいました。 なんとか自力で出来る事を探ろうと3日間粘ったのですがせめてヒントだけでもと、こちらに戻ってきてしまいました。 コメント頂けますと幸いです。 また、これはRandomForestの方のコードとベイズ最適化の方と共通の疑問なのですが、コードの終盤にある ”学習モデルにテストデータを与える”、からの下りにあるテストデータとはsplit = 2で指定している検証データとは別なのでしょうか、私の中で検証データとテストデータは別物という意識はあったのですが、その場合ここで使用しているテストデータとはどのファイルのことなのか、と疑問に思ってしまいました。こちらもご教示頂けますと幸いです。
PondVillege

2022/12/03 07:34

補足忘れてました,optunaはGoogle ColabのPython環境においてデフォルトでインストールされているものではないので,次のようにしてインストール願います !python -m pip install optuna もちろん,import optunaのインポート文はインポート系統でまとめてもらっても大丈夫です. あと,この時期は論文執筆にあたってかなり切羽詰まる時期だと思いますので,あまり時間をおかず質問して大丈夫です. > コードの終盤にある”学習モデルにテストデータを与える”、からの下りにあるテストデータとはsplit = 2で指定している検証データとは別なのでしょうか ここでは同じ物で扱いました.普通は別物ですが,質問者様にそのようなデータの用意があるか不明だったので,教師データ群から抜き出した物をそのままテストデータとして扱いました. 普通は教師データ群から抜き出した傾向が似ているデータなどを検証用データと呼び,汎化性能の確認を行うために,教師データ群とは異なる傾向のデータ群をテストデータと呼ぶことが多いです. 仮に今回のタスクで言えば走行データの中でも整理された道で計測したデータと,凹凸の激しい荒れた道を走行したデータなどが存在していて,前者の方を教師データ群にしておき,後者をテストデータにする.みたいなことは考えられます.しかしデータ総数が少ないようでしたので,学習モデルに与えてないデータであるという点から検証用データとテストデータを混同して扱っています.傾向は似ててもモデルに与えていなければある程度の汎化性能の確認は可能ですので
do-shiro-to

2022/12/03 12:34

ps_aux_grep様、コメント頂きありがとうございます。 >optunaはGoogle ColabのPython環境においてデフォルトでインストールされているものではない そうだったのですね、確かにpip install自体はpytonで使うことがあるのを失念していました。アドバイス通りインストールして実装したいと思います! >論文執筆にあたってかなり切羽詰まる時期だと思いますので,あまり時間をおかず質問して大丈夫です 仰るとおりで丁度切羽詰まってしまっております…。本当にありがとうございます。 >普通は教師データ群から抜き出した傾向が似ているデータなどを検証用データと呼び,汎化性能の確認を行うために,教師データ群とは異なる傾向のデータ群をテストデータと呼ぶことが多い 私自身こう認識しておりました。ですが私の用意しているデータ総数の少なさまで考慮して頂きありがとうございます。 ちなみになのですが、カーブも直進も20種類ずつに増やして用意したとして、学習モデルを生成して検証データとは別にテストデータを指定してモデルに入力して分類し、精度を確認することは可能でしょうか。テストデータは別でカーブと直進を一つずつ用意すると想定しております。
PondVillege

2022/12/03 13:02

> 検証データとは別にテストデータを指定してモデルに入力して分類し、精度を確認することは可能でしょうか。 可能です,適宜ファイルからデータを読み出して利用ください.
do-shiro-to

2022/12/03 13:25

ps_aux_grep様、ありがとうございます。 テストデータを別途読み出す方法を調査し、試行したいと思います。
do-shiro-to

2022/12/03 21:10 編集

現在のコードにある split = 2 # 最初の2ファイルは検証用データにする の部分が今回で言う検証データ(テストデータ)の指定になっていると考えているのですが、この最初の2ファイルとは、ディレクトリ構造で言うところのcurveの中の01.csvとstraightの中の01.csvの2ファイルとなっているのでしょうか また、この指定するデータを変えようと思ったらGoogleDrive上でファイルの順番を入れ替えるといった手法でも可能なのでしょうか 検証データと別にテストデータを指定しようとしていましたが、現在使っているディレクトリから指定することができるならその方が良いと思い、質問させていただきました。 少し内容が逸れてしまうかもしれないのですが、.shapeでデータの中身を確認するとx_train.shapeは(1485,93,3)、x_valid.shapeは(293,93,3)、y_train.shapeは(1485,1)、y_valid.shapeは(293,1)となっており、元々用意していたcsvファイルは4列のものだったのですが、データの前処理を経た物を訓練データと検証データとして使用しているからという解釈で間違いないでしょうか。 また、yは行と列を表していると考えたのですがxの方の3は1485行、93列と3は何の数値なのでしょうか。 特に2ファイルを検証データに使用とあったのですが、これは2ファイルを順番に組み合わせた物なのか、そうで無いのかを理解しなければテストデータを指定してもできているか判断できないと思い、質問させていただきました。 お答えいただけますと幸いです。 追記 このコメントで言う.shapeを試したときのディレクトリ構造は、curve内に11ファイル、straight内に9ファイルという状態です。
do-shiro-to

2022/12/03 21:13

追記 >指定するデータを変えようと思ったらGoogleDrive上でファイルの順番を入れ替えるといった手法でも可能なのでしょうか 実際に試してみようと思い、ディレクトリ内でファイル名の一つの頭にAを入れることで順番を入れ替えてみましたが、正解率は変わらなかったため別の方法を模索中です。
PondVillege

2022/12/04 11:57 編集

>この最初の2ファイルとは、ディレクトリ構造で言うところのcurveの中の01.csvとstraightの中の01.csvの2ファイルとなっているのでしょうか glob()が取り出した順なので番号順か保証できないです.sorted(glob())のようにしてやることで文字列的に昇順となるようにすることはできます.したがって, > この指定するデータを変えようと思ったらGoogleDrive上でファイルの順番を入れ替えるといった手法でも可能なのでしょうか は不可能です. .shapeについてですが,データ件数N, 波長L, チャネル数Cとして(N, L, C)のようになっています. 現状trainは, N = 1485, L = 93, C = 3ですね. * DataAugmentationを行ったのでCSVファイルの量より大きいN = 1485 * 最小のcsvファイルの長さがMだとすると,L = int(0.9 * M)として設定したものになります.最小で103行ぐらいだったのではないでしょうか.Google Colabにも書いた通り,最小ファイル長より小さい値であれば関数data_augmentationに渡すrollはなんでもいいです. * Cに関してはCSVが4列だったもののうち,合成加速度はあまり使えないとおっしゃっていたので,その前の3つのxyzを利用したので3チャンネルとなっています. 一般的に機械学習で波形を扱う場合は,(N, L, C)や(N, C, L)の形式でないといけない(Tensorflow, Kerasは前者, PyTorchは後者である必要がある)ため一般化しておいたまでのことです. 検証に用いた各2ファイルも,93行ごとにサンプルとってデータを増やして扱っています.もし検証用ファイルのうち1つ目が105行あったら,1-93行目,2-94行目,3-95行目,...,12-104行目,13-105行目でサンプリングした計13データが検証データに追加されます. なので,ファイル数というより,ファイルの中身によってデータ数Nが決まっていると考えていただけると良いかと思います. よって > 特に2ファイルを検証データに使用とあったのですが、これは2ファイルを順番に組み合わせた物なのか、そうで無いのか という質問には,「データを増やしつつ順番に組み合わせたものである」という回答になるかと思います.
do-shiro-to

2022/12/04 14:46 編集

ps_aux_grep様、ご回答頂きありがとうございます。 >sorted(glob())のようにしてやることで文字列的に昇順となるようにすることはできます globの前にsortedを入れることで昇順にすれば、多少強引でもsplit=2の2ファイルを選ぶことは可能という解釈でよろしいでしょうか。しかしこれが可能だとしてもテストデータにディレクトリ内から指定した2ファイルを使うと言うことにはならなさそうですね… >最小で103行ぐらいだったのではないでしょうか 仰るとおり最小104行でした。 >合成加速度はあまり使えないとおっしゃっていたので,その前の3つのxyzを利用したので3チャンネルとなっています つまり、もし合成加速度を使おうと思ったらpd.read_csv(file).values[:, :4]にしたり、パラメータを増やしてxとyの差や標準化を行ったx,y,z軸加速度も使おうと思ったら、どんどん数字を増やしていけば良いのでしょうか。 これまでは使用するパラメータを増やしたときは元々のcsvファイルをx軸加速度、合成加速度、xとyの差、標準化x軸加速度の4列にしていたのですが、おそらくこれではyの情報やzの情報が抜けるせいで参照するデータの内容が変わりすぎてこれまた意味の分からない分類器ができあがってしまっているような気がしてしまいます。 >検証に用いた各2ファイルも,93行ごとにサンプルとってデータを増やして扱っています >「データを増やしつつ順番に組み合わせたものである」 data_augmentationはモデル生成にあたってデータを増やす目的で行っていたと考えていたのですが、検証データにも同じ加工をしているのは何か理由があるのでしょうか。私の現状のイメージとして、データを増やしてモデルを生成し、そのモデルにテストデータとして無加工のcsvファイル(カーブか直進か)を入力することで、正解率を出力することができると考えていたのですがそういう方法が取れるわけでは無いと考えた方がよいでしょうか。 追記 検証データも学習モデルと同じ加工をして形を揃えないと分類する際に全く違う種類のデータになってしまうからという考え方はまた別の問題なのでしょうか。
PondVillege

2022/12/04 14:56

> 多少強引でもsplit=2の2ファイルを選ぶことは可能 はいそうです. > もし合成加速度を使おうと思ったらpd.read_csv(file).values[:, :4]にしたり、パラメータを増やしてxとyの差や標準化を行ったx,y,z軸加速度も使おうと思ったら、どんどん数字を増やしていけば良いのでしょうか。 はい,適宜CSVの列番号と合わせて利用ください. > おそらくこれではyの情報やzの情報が抜けるせいで参照するデータの内容が変わりすぎてこれまた意味の分からない分類器ができあがってしまっているような気がしてしまいます。 そうですね,普通,データの特性に合わせて分類器を変更するべきです.xyzで同一ならまだしも,差分波形や標準化波形は別の分類器パラメータが割り当てられるべきだと考えます. > 検証データにも同じ加工をしているのは何か理由があるのでしょうか 検証データのうち,どこの93行を抜き出すか,みたいな話をすることになりそうだったので,一応全域に対して識別できるか判断したく,同じ加工をしました.仰る通り検証データを増やす必要はないものの,ニューラルネットやRandomForestを使うときは波長は同じでなければいけないので一般化のために,このようにしていました.作成したLinearWaveClassifierにその制約はないので,CSVファイル全域を渡して大丈夫です. > 検証データも学習モデルと同じ加工をして形を揃えないと分類する際に全く違う種類のデータになってしまうからという考え方はまた別の問題なのでしょうか。 はい,今回たまたまLinearWaveClassifierは任意波長を受け付けることのできるモデルですが,RandomForestやニューラルネットで扱う場合は同じ形にする必要があります.
do-shiro-to

2022/12/04 15:35 編集

ps_aux_grep様、コメント頂きありがとうございます。 >> 多少強引でもsplit=2の2ファイルを選ぶことは可能 はいそうです. sortedを試してみたところ、昇順にしてからディレクトリ内のファイルの名前を変更して順番を変えてみたら、正解率も変化を確認できました。ありがとうございます。 >データの特性に合わせて分類器を変更するべきです.xyzで同一ならまだしも,差分波形や標準化波形は別の分類器パラメータが割り当てられるべきだと考えます. xyzと同時に差分や標準化をパラメータとして使用するのではなく、個々でモデルを生成してみたいと思います。 >ニューラルネットやRandomForestを使うときは波長は同じでなければいけないので一般化のために,このようにしていました なるほど、RandomForestでは必要なのですね。では、RandomForestでもLinerWaveどちらでも使用した検証データが一般化される前、どのファイルなのかを確認する方法はあるのでしょうか。 >作成したLinearWaveClassifierにその制約はないので,CSVファイル全域を渡して大丈夫 ありがとうございます。検証データにcsvファイル全域を渡すために、test = pd.read_csvのような形で試してみます。
PondVillege

2022/12/04 16:26 編集

> RandomForestでもLinerWaveどちらでも使用した検証データが一般化される前、どのファイルなのかを確認する方法はあるのでしょうか。 適宜load_data()を書き換えれば,x_trainやx_validのどのindexはどのファイル名であったのか,みたいな記述は可能です.一般には,元ファイル名を確認することよりも,検証データそのものを表示/可視化してしまって確認することが多いです. > 検証データにcsvファイル全域を渡すために、test = pd.read_csvのような形で試してみます。 入力データ(x_trainやx_valid)にまとめたように,(N, L, C)形式であればmodel.predict()が使えますが, test = pd.read_csv()として得られる単一データであれば(1, L, C)のようにreshapeしてmodel.predict()に渡すか,単一データ用のmodel._predict()を利用してください. accuracy_scoreの利用を考えると前者の(N, L, C)形式で渡すことを推奨します. model.predict(np.array([pd.read_csv("filename.csv").values[:, :3]])) で(1, L, 3)になると思います.
do-shiro-to

2022/12/04 17:25 編集

ps_aux_grep様、コメント頂きありがとうございます。 >検証データそのものを表示/可視化してしまって確認することが多いです 現状検証データの可視化として、df2 = pd.DataFrame(data=y_valid) df2.plot() を使用しているのですが、これは既に2値化された物で検証データそのものの表示とはなっていないでしょうか。質問本文の最後に可視化した画像を追加させて頂きます。見て頂けますと幸いです。 >適宜load_data()を書き換えれば,x_trainやx_validのどのindexはどのファイル名であったのか,みたいな記述は可能 load_data内の読み込むフォルダを変える、と言うわけではなく新しくそのためのコードを追加すると言うことでしょうか。 >test = pd.read_csv()として得られる単一データであれば(1, L, C)のようにreshapeしてmodel.predict()に渡すか,単一データ用のmodel._predict()を利用してください. pd.read_csv()ではなくmodel.predict(np.array([pd.read_csvの方が今回の場合は適しているのですね…!ありがとうございます。試してみます。 追記 >model.predict(np.array([pd.read_csvの方が今回の場合は適しているのですね…!ありがとうございます。試してみます。 #テストデータを与えて各データの種類を推測 y_pred = model.predict(x_valid)の部分を y_pred = model.predict(np.array([pd.read_csv("02.csv").values[:, :3]]))と言う風に変更してみました。ここではエラーは出なかったのですが、その後の # テストデータのラベルを与えて答え合わせ score = accuracy_score(y_valid, y_pred) print(f"正解率:{score * 100}%") の部分で、ValueError: Found input variables with inconsistent numbers of samples: [323, 1]というエラーメッセージが返ってきました。サンプル数が一致しない入力変数とあり、これまでにあまり見たことのないメッセージで、どこをいじるのか見当が付きませんでした…。今回読み込ませたcsvファイルは、学習モデル生成時には使用していないデータで、形は220行4列にはしていたのでサンプル数が一致しないことは無いと思ったのですが、ここで言うサンプル数は別の要素なのでしょうか。
PondVillege

2022/12/05 08:54

> 現状検証データの可視化として、df2 = pd.DataFrame(data=y_valid) df2.plot() を使用している 普通,model.predict()に入力するのは入力値のみです.なので,model.predict(x_valid)としてy_predを吐き出させ,y_validと比較するものです. > load_data内の読み込むフォルダを変える、と言うわけではなく新しくそのためのコードを追加する はい.その方が良いかと思います. > ValueError: Found input variables with inconsistent numbers of samples: [323, 1] x_validとy_validなら比較可能なのでaccuracy_scoreは出ます.しかし,単一データが格納されているであろう02.csvの予測出力y_predと複数データの結果が格納されているy_validは比較不可能です. 例えば,02.csvはカーブをサンプルしたものであれば,y_valid = [[1]]にするべきですし,直進であればy_valid = [[0]]としておくべきです.追記で例示します.
do-shiro-to

2022/12/05 16:37

ps_aux_grep様、コメント並びに回答の編集での例示頂きありがとうございます。 >x_validとy_validなら比較可能なのでaccuracy_scoreは出ます.しかし,単一データが格納されているであろう02.csvの予測出力y_predと複数データの結果が格納されているy_validは比較不可能です. >x_test = np.array([ pd.read_csv("02.csv").values[:, :3], # 任意のcsvファイルを与えまくる pd.read_csv("03.csv").values[:, :3], このようにして複数のcsvファイルを与え実行して、カーブと直進合計で13個のファイルを読み込ませようとしたのですが、x_test.shapeは(13)、y_test.shapeは(13,1)になり、グラフにしてみても読み込ませた加速度データではなく、y_test=で手動で指定した0か1かで表されました。これがデータを単一化すると言うことでよろしいでしょうか。
PondVillege

2022/12/05 18:47

> x_test.shapeは(13) (13, L, 3)が正しいはずです.CSVの見直しのほどお願いします.y_test.shapeは正しいです. 補足忘れていましたが,np.array()のためにはCSVファイルの行数が同じでなければエラーになるため,行数が異なる場合は x_test = [ pd.read_csv("02.csv").values[:, :3], pd.read_csv("03.csv").values[:, :3], ] のようにしてnp.array()を省略してください.その際にはx_test.shapeで確認することはできなくなりますが,今回のモデルでファイル行数が異なることを許容している弊害が出ているだけのことです. > グラフにしてみても読み込ませた加速度データではなく、y_test=で手動で指定した0か1かで表されました。これがデータを単一化すると言うことでよろしいでしょうか。 どれをグラフにしたのでしょうか.y_testやy_predグラフにしてもそれは何ら意味のないものです.0か1か予測した結果を可視化したいならConfusion Matrixを作成するべきです. 単一データだけ利用する方法は,モデルの扱えるデータ形式(N, L, C)において,データ数Nの次元があるようにデータを用意することの話で, x_test = [ pd.read_csv("02.csv").values[:, :3], ] y_test = [ [1] ] とすると,.shapeは使えないものの,状態としては(1, L, 3)となってモデルが扱える.かつaccuracy_score(y_pred, y_test)での比較も可能である. もしくは,今回LinearWaveに特別に用意した単一データ予測用のmodel._predict()にデータ形式(L, C)の形式で与えることのできる x_test = pd.read_csv("02.csv").values[:, :3] y_pred = model._predict(x_test) 状態にすることが可能です.しかしこの場合accuracy_score()は利用できないです.という話でした. このうち,前者の方を拡張して複数のファイルの入出力を並べただけなので追加したコードは「単一化する」という話ではなく,ただモデルおよびaccuracy_scoreが標準的に扱える形式にしたまでのことです.これらはデータの整形の一環でしかないです.これが当たり前にできないと実験なんてできないと思います.
do-shiro-to

2022/12/07 18:14 編集

ps_aux_grep様、コメント頂きありがとうございます。 >(13, L, 3)が正しいはずです.CSVの見直しのほどお願いします.y_test.shapeは正しいです. >CSVファイルの行数が同じでなければエラーになる 今回読み込ませようとしたcsvファイルはモデル生成に入れていたファイルとは異なるファイルだったので行数も異なっていました。x_test = [ pd.read_csv("02.csv").values[:, :3], pd.read_csv("03.csv").values[:, :3], ]で試してみます。 >どれをグラフにしたのでしょうか.y_testやy_predグラフにしてもそれは何ら意味のないものです y_testやy_predをグラフにしてしまっていました…これまでのvalidとpredのようにどれ程一致するのかを見ようとしていました。 >0か1か予測した結果を可視化したいならConfusion Matrixを作成するべき ありがとうございます。confusion_matrix(y_test, y_pred)で試してみます。 >.shapeは使えないものの,状態としては(1, L, 3)となってモデルが扱える accuracy_score(y_pred, y_test)が利用できると言うことは、precisionやrecallも利用できそうで良かったです。とにかく、一度np.array()を省略してみます。 >これらはデータの整形の一環でしかないです.これが当たり前にできないと実験なんてできないと思います. 単一化についての理解が及んでいませんでした…申し訳ございません。 追記 >confusion_matrix(y_test, y_pred)で試してみます。 試してみましたが、 [[5 0] [1 7]] となってしまいました。流石に、ただ単純にこのコードを追加したら分類した結果が見られるわけではなさそうですね…
PondVillege

2022/12/07 18:30 編集

そのconfusion_matrixはかなりいい結果を出してますよ?92.3%の正解率が出てますね precisionは0.83 recallは0.41 ですね
do-shiro-to

2022/12/07 18:52

ps_aux_grep様、コメントありがとうございます。 これは良い結果なのでしょうか?precisionは1.0でrecallは0.875でした。ですが、y_testの中身は以前と変わらずy_test = [ [1] ]で読み込んだ13個のファイルが0か1でそのまま出力されるだけで、y_predの中身は13行でtrueかfalseで出力されました。これはつまり、13個のファイルが1か0かを分類した結果が示されたと言うことでよろしいでしょうか。
PondVillege

2022/12/07 19:41

> precisionは1.0でrecallは0.875でした。 見てるindexが逆だったみたいですね,紛らわしくてすみません. > y_predの中身は13行でtrueかfalseで出力されました。これはつまり、13個のファイルが1か0かを分類した結果が示されたと言うこと はい.そうです.[[5 0], [1 7]]ということでしたので,1つだけ予測を外したケースがあります.
do-shiro-to

2023/02/16 05:22

ps_aux_grep様、遅れてしまい申し訳ございません。 最終的に、頂いたLinearWaveClassifierで自分の思った出力結果を得ることができ、納得してもらえる説明もできたため、報告させて頂きます。 この度は、何度も助けていただき本当にありがとうございました。
PondVillege

2023/02/16 12:02

力添えできてよかったです.お疲れ様でした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問