(x,y,z)の3軸での加速度を用いた活動体位の予測の機械学習について
こんにちは、Pythonを学び始めて1ヶ月の初心者です。とても初歩的なことかもしれないのですが質問させてください。
オンラインコースの課題で上記のような予測をするプログラムを作成するというものがあり、取り組んでいます。実装してみたのですが、制度がまったく出ず困っています。入力の値や各層の実装については問題ないと思うのですが、出力を見てみると結果的に全て一つの答えのみになってしまっています。どこが問題なのか等アドバイスをいただければ幸いです。Pythonは自学のみであり、周りに聞ける人もおらず八方塞がりなのでヒントだけでもいただけましたら幸いです。よろしくお願いいたします。
課題の詳細です。
このプロジェクトでは、スマートフォンの3軸加速度計データから身体活動のタイプ(例、歩く、階段を上る)を予測しようとします。
入力データ
このプロジェクトのトレーニングに使用される入力データは、2つのファイルで構成されています。最初のファイルtrain_time_series.csvには、収集された生の加速度計データが含まれており、その形式は次のとおりです。
タイムスタンプ、UTC時間、精度、x、y、z
タイムスタンプ列を時間変数として使用できます。また、ここではx、y、zとラベル付けされた最後の3つの列も必要です。これらは、3つの直交軸のそれぞれに沿った線形加速度の測定値に対応しています。
2番目のファイルtrain_labels.csvには身体活動のラベルが含まれており、これらのラベルを使用してモデルをトレーニングします。身体活動にはそれぞれ整数で番号が付けられています。1 =立つ、2 =歩く、3 =階段を下る、4 =階段を上がる、の4項目です。加速度計は高周波数でサンプリングされるため、train_labels.csvのラベルは、train_time_series.csvの10回ごとの観測に対して提供されます。
活動分類
目標は、さまざまな身体活動をできるだけ正確に分類することです。コードをテストするために、test_time_series.csvというファイルも提供され、プロジェクトの最後に、このテストデータセットのコードによって予測されるアクティビティラベルを提出します。コーススタッフだけがテストデータに対応する真のラベルを持ち、コードの正確さは正しい分類のパーセンテージとして決定されます。どちらの場合も、トレーニングとテストの場合、入力ファイルは単一(3次元)の時系列で構成されていることに注意してください。コードの精度をテストするには、予測をCSVファイルとしてアップロードするように求められます。 test_labels.csvと呼ばれるこのファイルは提供されていますが、予測に必要なタイムスタンプのみが含まれています。対応するクラス予測(1、2、3、4)を追加して、このファイルを拡張する必要があります。
該当のソースコード
Python
1 2%matplotlib inline 3 4import numpy as np 5import pandas as pd 6import matplotlib.pyplot as plt 7 8 9 10def to_input(df): 11 df["synthetic_acce"]=np.sqrt(df.x**2+df.y**2+df.z**2) 12 #合成加速度を計算しn×10行列を作成します 13 #まず、入力データは10こで1つの動きを規定しています。(ex.入力データのインデックス0−9が一つの対位(座る)) 14 #そのため、1サンプルを10この要素を含む配列に変換します。 15 #そのためのインデックス として以下を書きます 16 index = df.index 17 index_s1= index[index%10==1] 18 index_s2= index[index%10==2] 19 index_s3= index[index%10==3] 20 index_s4=index[index%10==4] 21 index_s5=index[index%10==5] 22 index_s6=index[index%10==6] 23 index_s7=index[index%10==7] 24 index_s8= index[index%10==8] 25 index_s9= index[index%10==9] 26 index_s10= index[index%10==0] 27 #標準化させるために平均と標準偏差を計算します。 28 ave_input=np.array([np.average(df.synthetic_acce[i:i+10]) for i in range(0,len(df.synthetic_acce),10)]) 29 std_input=np.array([np.std(df.synthetic_acce[i:i+10]) for i in range(0,len(df.synthetic_acce),10)]) 30 #合成加速度の値を作ったインデックスを利用して取り出しそれぞれを標準化させます 31 s1=(df.synthetic_acce.values[index_s1] - ave_input) / std_input 32 s2= (df.synthetic_acce.values[index_s2]- ave_input) / std_input 33 s3=(df.synthetic_acce.values[index_s3]- ave_input) / std_input 34 s4=(df.synthetic_acce.values[index_s4]- ave_input) / std_input 35 s5=(df.synthetic_acce.values[index_s5]- ave_input) / std_input 36 s6= (df.synthetic_acce.values[index_s6]- ave_input) / std_input 37 s7=(df.synthetic_acce.values[index_s7]- ave_input) / std_input 38 s8= (df.synthetic_acce.values[index_s8]- ave_input) / std_input 39 s9= (df.synthetic_acce.values[index_s9]- ave_input) / std_input 40 s10= (df.synthetic_acce.values[index_s10]- ave_input) / std_input 41 #計算した10この要素を積み重ねn×10の行列を作成します 42 43 c=np.vstack((s1,s2,s3,s4,s5,s6,s7,s8,s9,s10)).T 44 #特徴を増やすために上記の操作をx軸、y軸、z軸でも行います。インデックスはそのまま使用しています。 45 ave_x=np.array([np.average(df.x[i:i+10]) for i in range(0,len(df.x),10)]) 46 std_x=np.array([np.std(df.x[i:i+10]) for i in range(0,len(df.x),10)]) 47 48 x1=(df.x.values[index_s1]- ave_x) / std_x 49 x2= (df.x.values[index_s2]- ave_x) / std_x 50 x3=(df.x.values[index_s3]- ave_x) / std_x 51 x4=(df.x.values[index_s4]- ave_x) / std_x 52 x5=(df.x.values[index_s5]- ave_x) / std_x 53 x6= (df.x.values[index_s6]- ave_x) / std_x 54 x7=(df.x.values[index_s7]- ave_x) / std_x 55 x8= (df.x.values[index_s8]- ave_x) / std_x 56 x9= (df.x.values[index_s9]- ave_x) / std_x 57 x10= (df.x.values[index_s10]- ave_x) / std_x 58 x=np.vstack((x1,x2,x3,x4,x5,x6,x7,x8,x9,x10)).T 59 60 61 ave_y=np.array([np.average(df.y[i:i+10]) for i in range(0,len(df.y),10)]) 62 std_y=np.array([np.std(df.y[i:i+10]) for i in range(0,len(df.y),10)]) 63 64 y1=(df.y.values[index_s1]- ave_y) / std_y 65 y2= (df.y.values[index_s2]- ave_y) / std_y 66 y3=(df.y.values[index_s3]- ave_y) / std_y 67 y4=(df.y.values[index_s4]- ave_y) / std_y 68 y5=(df.y.values[index_s5]- ave_y) / std_y 69 y6= (df.y.values[index_s6]- ave_y) / std_y 70 y7=(df.y.values[index_s7]- ave_y) / std_y 71 y8= (df.y.values[index_s8]- ave_y) / std_y 72 y9= (df.y.values[index_s9]- ave_y) / std_y 73 y10= (df.y.values[index_s10]- ave_y) / std_y 74 y=np.vstack((y1,y2,y3,y4,y5,y6,y7,y8,y9,y10)).T 75 76 ave_z=np.array([np.average(df.z[i:i+10]) for i in range(0,len(df.z),10)]) 77 std_z=np.array([np.std(df.z[i:i+10]) for i in range(0,len(df.z),10)]) 78 79 z1=(df.z.values[index_s1]- ave_z) / std_z 80 z2= (df.z.values[index_s2]- ave_z) / std_z 81 z3=(df.z.values[index_s3]- ave_z) / std_z 82 z4=(df.z.values[index_s4]- ave_z) / std_z 83 z5=(df.z.values[index_s5]- ave_z) / std_z 84 z6= (df.z.values[index_s6]- ave_z) / std_z 85 z7=(df.z.values[index_s7]- ave_z) / std_z 86 z8= (df.z.values[index_s8]- ave_z) / std_z 87 z9= (df.z.values[index_s9]- ave_z) / std_z 88 z10=(df.z.values[index_s10]- ave_z) / std_z 89 90 z=np.vstack((z1,z2,z3,z4,z5,z6,z7,z8,z9,z10)).T 91 #計算した物を全て積み重ね、それぞれ10この要素を合わせたn×40の行列を作成します。 92 d=np.hstack((x,y,z,c)) 93 94 return d 95 96 97 98def to_one_hot(df): 99 #解答のラベルが1−4の整数であるので、ワンホット表現に変換します。 100 101 target_vector = [0,1,2,3] # 整数をベクトルにします 102 n_labels = len(np.unique(target_vector)) # 解答は 4種類です 103 ind=np.eye(n_labels)[target_vector] 104 x=[] 105 for i in df["label"]: 106 if i ==1 : 107 x.append(ind[0]) 108 elif i ==2: 109 x.append(ind[1]) 110 elif i ==3: 111 x.append(ind[2]) 112 elif i ==4: 113 x.append(ind[3]) 114 else: 115 x.append(np.zeros(4))#エラー対策でそれ以外はゼロの配列にします。 116 df["one_hot"]=x 117 118 v=np.zeros(4) 119 for i in df.one_hot.values: 120 v=np.vstack((v,i)) 121 122 vl = np.delete(v, 0, 0) 123 return vl 124 125#入力データはなぜかぴったりではなかったので3470こまでを取り出しています。 126df_input_train=pd.read_csv("https://courses.edx.org/assets/courseware/v1/b98039c3648763aae4f153a6ed32f38b/asset-v1:HarvardX+PH526x+1T2020+type@asset+block/train_time_series.csv")[:3740] 127 128 129#解答のラベルです 130df_correct_train=pd.read_csv("https://courses.edx.org/assets/courseware/v1/d64e74647423e525bbeb13f2884e9cfa/asset-v1:HarvardX+PH526x+1T2020+type@asset+block/train_labels.csv", index_col=0)[:374] 131 132 133 134input_data = to_input(df_input_train)# 入力データを定義します 135correct_data =to_one_hot(df_correct_train) # 正解のラベルを定義します 136 137input_train=input_data[0::2]#訓練データとテストデータに2分割させます。こちらは訓練データにします 138correct_train=correct_data[0::2 ]#こちらは訓練データの解答となります 139input_test=input_data[1::2]#訓練データとテストデータに2分割させます。こちらはテストデータにします 140correct_test=correct_data[1::2]#こちらはテストデータの解答となります 141 142 143 144n_data = len(correct_data) # サンプル数を定義します 145n_train =len(input_train) 146n_test =len(input_test) 147 148#テストであるかどうかを判定します。 149is_train=True 150 151# -- 各設定値 -- 152n_in = 40 # 入力層のニューロン数(s:合成加速度10+x:x軸加速度10+y:y軸加速度10z:z軸加速度10=合計40です) 153n_mid =25 # 中間層のニューロン数 154n_out = 4 # 出力層のニューロン数 155 156wb_width = 0.1 # 重みとバイアスの広がり具合 157eta = 0.01 # 学習係数 158epoch = 1000 159batch_size = 10 160interval = 100 # 経過の表示間隔 161 162#以下の各層の実装は’はじめてのディープラーニング’著 我妻幸長 のIrisの品種分類の部分を参考にしています。 163#文字数超えて書けず、ところどころ抜かして書きました。中間層活性化:ReLU、出力層活性化:ソフトマックス関数、損失関数:交差エントロピー誤差、最適化アルゴリズム:AdaGrad、ドロップ層:2層です。 164 165 166#dropout層を追加 167class Dropout: 168 def __init__(self, dropout_ratio): 169 self.dropout_ratio=dropout_ratio 170 171 def forward(self,x,is_train): 172 if is_train: 173 rand=np.random.rand(*x.shape) 174 self.dropout=np.where(rand>self.dropout_ratio,1,0) 175 self.y=x*self.dropout 176 else: 177 self.y=(1-self.dropout_ratio)*x 178 179 def backward(self,grad_y): 180 181 self.grad_x=grad_y* self.dropout_ratio 182 183#各層の初期化 184middle_layer_1=MiddleLayer(n_in,n_mid) 185dropout_1=Dropout(0.9) 186middle_layer_2=MiddleLayer(n_mid,n_mid) 187dropout_2=Dropout(0.5) 188output_layer=OutputLayer(n_mid,n_out) 189 190#順伝播 191def forward_propagation(x,is_train): 192 middle_layer_1.forward(x) 193 dropout_1.forward(middle_layer_1.y,is_train) 194 middle_layer_2.forward(dropout_1.y) 195 dropout_2.forward(middle_layer_2.y,is_train) 196 output_layer.forward(dropout_2.y) 197#逆伝播 198def backpropagation(t): 199 output_layer.backward(t) 200 dropout_2.backward(output_layer.grad_x) 201 middle_layer_2.backward(dropout_2.grad_x) 202 dropout_1.backward(middle_layer_2.grad_x) 203 middle_layer_1.backward(dropout_1.grad_x) 204 205# -- 重みとバイアスの更新 -- 206def uppdate_wb(): 207 middle_layer_1.update(eta) 208 middle_layer_2.update(eta) 209 output_layer.update(eta) 210 211# -- 誤差を計算 -- 212def get_error(t, batch_size): 213 return -np.sum(t * np.log(output_layer.y+ 1e-7)) / batch_size # 交差エントロピー誤差 214 215 216 217 # -- 学習 -- 218 index_random = np.arange(n_train) 219 np.random.shuffle(index_random) # インデックスをシャッフルする 220 for j in range(n_batch): 221 222 # ミニバッチを取り出す 223 mb_index = index_random[j*batch_size : (j+1)*batch_size] 224 x = input_train[mb_index, :] 225 t = correct_train[mb_index, :] 226 227 228 forward_propagation(x,is_train) 229 backpropagation(t) 230 231 # 重みとバイアスの更新 232 uppdate_wb() 233 234
試したこと
各層のニューロン数や重み、バッチ数の変更をしたり特徴を足し引きしたり、ドロップアウトの割合を変えたりとりあえず思いつくことはやってみたのですが、制度は60パーセントを超えませんでした。出力層のyの値を見てみると最大の要素はインデックスの1に全て集まっておりargmaxを使った時に全て1になっていました。各層の実装は'はじめてのディープラーニング’著 我妻幸長 のIrisの品種分類の部分を参考に書いたためミスはないと思います。入力のデータの前処理がうまくいっていないのかと思うのですが原因がわかりません。
補足情報(FW/ツールのバージョンなど)
jupyter noteで動かしています。全く初心者で質問の際に何を書けばいいのかということもわかっておりませんので追加で必要な部分があればぜひそこも教えていただければと思います。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/16 00:07