8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

これは深層学習以外の機械学習と応用技術 by QuantumCore Advent Calendar 2019の9日目の記事です。

はじめに

こんばんは、@saitoxuです。
本稿ではQoreSDKを使った簡単な回帰タスクの方法を説明します。
ちなみに自分は時系列解析周りの知識はあまりないので、何か間違ってること等ありましたら(優しく)コメントで教えてください:bow:

QoreSDKを使った回帰タスク

今回は正弦波(sine)の予測をしてみます。
次のようにsin関数から生成される時系列データの一部を学習させて、未来の時刻のsineの値を予測させるタスクです。

データの準備

最初にsine波のデータを準備します。

# sine波の長さ
t_length = 1000
# 分割するときのサイズ
t_width = 400

train_x = np.arange(t_length)
# 平均がsin(x), 分散0.1の正規分布に従う配列を生成
train_y = np.random.normal(np.sin(2 * np.pi * train_x / 100), 0.1)
x = []
y = []
for i in range(len(train_x) - t_width):
    x.append(train_y[i:i + t_width])
    y.append(train_y[i + t_width])

x = np.array(x)
y = np.array(y)

# 学習データとテストデータに分割
X_train = x[0:((t_length - t_width) // 2)]
X_test = x[((t_length - t_width) // 2):]
y_train = y[0:((t_length - t_width) // 2)]
y_test = y[((t_length - t_width) // 2):]

print(X_train.shape) # (300, 400)
print(X_test.shape) # (300, 400)

ここでは以下のことをやってます。

  1. 長さt_lengthのsine波を生成
  2. それを長さt_widthの部分波に分割
  3. t_length - t_width個の部分波ができるので、それを学習データとテストデータに分割

plt.plot(X_train[0])などとすると、次のような時系列データが生成されていることが分かります。
また、y_trainにはX_trainの最後の時刻$t$の次の時刻$t+1$の値が入っています。

image.png

前処理

前処理、と言っても特段することはないのですが、QoreSDKの学習関数の入力が(サンプル数, 時系列長, 変量数)なのでそのようにデータを変換します。

# 2次元配列だったのを3次元配列にしてるだけ
X_train = X_train.reshape([(t_length - t_width) // 2, t_width, 1])
X_test = X_test.reshape([(t_length - t_width) // 2, t_width, 1])

不整脈検出のサンプルではqore_sdk.featurizerモジュールqore_sdk.utilsモジュールを使って入力データに変換していましたが、今回のタスクで使ってみたところあまり良い精度が出なかったので(後述します)、上記のような変換としています。

学習

回帰タスクなので、qore_sdk.clientモジュールregression_train関数を使います。

client = WebQoreClient('username', 'password', endpoint='endpoint')
res = client.regression_train(X_train, y_train)
print(res) # {'res': 'ok', 'train_time': 6.9450061321258545}

username, password, endpointはご自分のものに変更してください。
だいたい10秒もあれば完了します。

予測と評価

学習したモデルを使って、テスト用データの予測をしてみます。

res = client.regression_predict(X_test)

予測値と正解データをプロットしてみると以下のようになります。

plt.plot(res['Y'], figure=plt.figure(figsize=(12.8, 4.8))) # 予測値(青)
plt.plot(y_test) # 正解(オレンジ)

image.png

だいたい正しく予測できているのが分かりました。
ちなみに次の関数を用意して、テストデータ以降の値も予測してみます。

# n個先の時刻の予測を行う
def predict(n):
    # X_test[-1]が最後の時刻のデータ
    data = X_test[-1].reshape(t_width)
    for _ in range(n):
        res = client.regression_predict([data[len(data) - t_width:]])
        data = np.append(data, res['Y'][0])
    return data[len(data) - n:]

実際に使ってみましょう。
100個先の時刻まで予測して結果をプロットしてみます。

result = predict(100)
plt.plot(result)

image.png

一応sineっぽい形状になりました。
ちなみにこれはQoreのAPIサーバに負荷をかけることになるので、$n$は小さな値で試してください :bow:

Featurizerを使ったがうまくいかなかった

次のようにQoreのFeaturizerを使ってデータを入力用の配列に変換したところ、今回のタスクではあまりうまく学習されませんでした。

width = 144
stepsize = 36
n_filters = 40

# ここで(サンプル数, 時系列長, 小時系列長)の配列を作成
X_train = sliding_window(X_train, width, stepsize)
X_test = sliding_window(X_test, width, stepsize)
print('X_train.shape:', X_train.shape)
print('X_test.shape:', X_test.shape)

# (サンプル数, 時系列長, 変量数)の配列に変換(Qoreへの入力となる)
featurizer = Featurizer(n_filters)
X_train = featurizer.featurize(X_train, axis=2)
X_test = featurizer.featurize(X_test, axis=2)
print(X_train.shape)
print(X_test.shape)

詳細は分かりませんが、Featurizerは中では周波数分解をやってるそうなので、今回のタスクのようなsine波は分割のしようがないためうまく学習されなかったのかなと思いました。

おわりに

QoreSDKを使って回帰タスクを行ってみました。
今後、Qoreを使って株価予測などの回帰問題をやってみたいという方の参考になれば幸いです。
今回使ったノートブックは下記のリポジトリに置いてるので、合わせてどうぞ。

saitoxu/qcore-advent-calendar

参考

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?