質問に掲載したコードを修正すれば、該当のソースコード部の最後にあるF値等を出力や、教師データを1か0でルール付けて学習などは可能か不可能か
可能です.こちらでは質問のデータを持ち合わせていないので,同様のデータ生成を行なって最終的な評価までのコードを書いてみました.
全てのCSVファイルが同じ行数であることを前提に書いています.変数roll
に全てのCSVファイルのうち1番小さい行数未満の値を代入すればなんでも良いです.そのときは全てのCSVファイルのサイズは同じでなくて構いません.130~240ぐらいとのことだったので,カーブの時間全体を覆えるデータ長を目視で確認して129以下の値を代入することが出来ます.
Python
1import numpy as np
2from glob import glob
3import csv
4import os
5
6# データ生成
7# 直進(straight)とカーブ(curve)のデータはそれぞれ同じフォルダに入っているものとして扱う
8os.makedirs("./data/straight/", exist_ok = True)
9os.makedirs("./data/curve/", exist_ok = True)
10
11def wave(name, t): # 時刻tにおけるデータを生成
12 if name == "straight":
13 return np.random.randn(4)
14 else:
15 return np.sin(t + np.random.randn(4))
16
17def make_data(name, n):
18 for file in range(n):
19 with open(f"./data/{name}/{file}.csv", "w") as f:
20 writer = csv.writer(f)
21 writer.writerow(["x", "y", "z", "res"]) # ヘッダ書き込み
22 for i in range(100): # 1ファイルのデータ長100で生成
23 writer.writerow(list(wave(name, i)))
24
25make_data("straight", 20)
26make_data("curve", 10)
27
28# ここから本質的な内容
29
30def load_csv(file, y_value): # ファイル名fileのCSV読み込み,1データを複数に分割する
31 # pandas.read_csv()を使わないで書いてみる
32 _x = list() # 1ファイルのデータすべて_xに格納する
33 with open(file, "r") as f:
34 reader = csv.reader(f)
35 header = next(reader) # ヘッダは読み飛ばし
36 for row in reader:
37 _x.append([float(col) for col in row[:3]])
38
39 # データ分割部
40 _x = np.array(_x) # ここの _x は pd.read_csv(file).values[:, :3] と同義だが一応フルスクラッチで書いてる
41 roll = int(len(_x) * 0.8) # データ長の8割を1データにしてrollさせる.
42 x, y = list(), list()
43 for r in range(len(_x) - roll): # 2割のデータ長さだけデータが作られる.
44 x.append(_x[r: r + roll])
45 y.append([y_value])
46 return np.array(x), np.array(y)
47
48def load_data(): # 全データ読み込み
49 split = 2 # 最初の2ファイルは検証用データにする
50 x_train, y_train, x_valid, y_valid = list(), list(), list(), list()
51 for name, v in zip(["straight", "curve"], [0, 1]): # straightは0,curveは1にする
52 for i, file in enumerate(glob(f"./data/{name}/*.csv")):
53 _x, _y = load_csv(file, v)
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
65# RandomForestでは1つの特長にベクトルを扱えないので,別のモデルを採用
66import tensorflow as tf
67from tensorflow.python import keras
68from keras.models import Sequential
69from keras.layers import Conv1D, Input, Flatten, Dense
70from keras.optimizers import Adam
71
72from sklearn.metrics import accuracy_score
73
74# 学習モデルを作成
75model = Sequential()
76model.add(Input(shape = x_train.shape[1:]))
77model.add(Conv1D(8, 4, strides = 2, activation = "tanh"))
78model.add(Conv1D(4, 4, strides = 2, activation = "tanh"))
79model.add(Conv1D(2, 4, strides = 2, activation = "tanh"))
80model.add(Flatten())
81model.add(Dense(1, activation = "sigmoid"))
82
83model.compile(
84 loss = "binary_crossentropy",
85 optimizer = Adam()
86)
87# model.summary() # モデル確認用
88
89# 学習モデルにデータを与えて学習させる
90model.fit(
91 x_train, y_train,
92 batch_size = 8,
93 epochs = 50,
94 validation_data = (x_valid, y_valid)
95)
96
97# テストデータを与えて各データの種類を推測
98# 0から1の 範囲 で得られるのでroundで 四捨五入 して0か1にする
99y_pred = np.round(model.predict(x_valid, batch_size = 8))
100
101# テストデータのラベルを与えて答え合わせ
102score = accuracy_score(y_valid, y_pred)
103print(f"正解率:{score * 100}%")
そもそも,RandomForestが時系列処理に向いているか,と聞かれればNoに近しい答えになると思います.
情報の取捨選択をしまくるので,時刻の前後関係などを見出すのことへの不得意さを否定できません.LSTMを使った方がより良い精度が得られると思います.
今回は,ある時刻の特徴量がxyzの3特長あるので1次元畳み込みを採用してみました(LSTMでも良い)が,もし合成加速度だけを使うならRandomForestも使えると思います.
上のコードでは,時系列データ分析の処理でやってはいけないことを念頭に,学習データに評価データが混じらないようにしています.注意して実装なさってください.
これは、一つのファイルにx、y、z軸のデータを作って同じ計測期間で複数のファイルをcurve1,curve2,curve3,straight1,straight2,straight3………のように作成し、その複数のファイルを同時に学習させるというイメージでよろしいでしょうか…?
はい,それで間違い無いです.その場合は上のコードにおけるload_csv()
を次のようにできます.
Python
1def load_csv(file, y_value):
2 return [pd.read_csv(file).values[:, :3]], [y_value]
ただこの場合だと,ファイル次第でデータ長が違う現状には適応できていないので,適宜データの長さを揃えるような処理を書き加えてください.「同じ計測期間で複数のファイルを作成」されて長さが揃ってるなら不要です.
機械学習をやるとはいえ,前処理や学習,評価にあたって書くプログラムはほとんど配列操作に関するものになります.配列の扱いに慣れておくことをおすすめします.
特に前処理なんて扱うデータが変われば書くコードも変わります.時系列データの前処理と画像処理の前処理,構造データの前処理や自然言語の前処理など色んな種類がある中で,自分の持っているデータの前処理を完璧にこなせるコードはこの世に無いと思ってプログラミングに取り組んでください.
あまりコードを書かれたことの無いようでしたので方針を示すためコードを全て書きましたが,前処理程度はPythonの基礎を押さえていれば書けるはずです.今後の研究進捗効率のためにも急がば回れ,プログラミング基礎の勉強を推奨しておきます.