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

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

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

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

Q&A

解決済

2回答

3126閲覧

python:mnistデータでknn

退会済みユーザー

退会済みユーザー

総合スコア0

Python

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

1グッド

2クリップ

投稿2017/12/01 16:21

###前提・実現したいこと
mnistデータでknnを実行したが、データサイズが大きいため処理に時間がかかる。
- 処理時間を高速にするにはどうするか。
- データサイズを指定して実行するにはどうすればよいのか。

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

データサイズが大きいため処理に時間がかかる。  - 処理時間を高速にするにはどうするか。  - データサイズを指定して実行するにはどうすればよいのか。

###該当のソースコード

python

1from collections import Counter 2from matplotlib import pyplot as plt 3from sklearn import datasets, model_selection, metrics 4from sklearn.model_selection import LeaveOneOut 5from sklearn.metrics import accuracy_score 6from sklearn.neighbors import KNeighborsClassifier 7import sklearn.datasets as datasets 8import numpy as np 9import time 10 11 12def main(): 13 # データをロード 14 mnist = datasets.fetch_mldata('MNIST original', data_home='data/src/download/') 15 16 # 特徴データとラベルデータを取り出す 17 features = mnist.data 18 targets = mnist.target 19 20 # 検証する近傍数 21 K = 10 22 ks = range(1, K + 1) 23 24 # 使う近傍数ごとに正解率&各経過時間を計算 25 accuracy_scores = [] 26 start = time.time() 27 for k in ks: 28 predicted_labels = [] 29 loo = LeaveOneOut() 30 for train, test in loo.split(features): 31 train_data = features[train] 32 test_data = targets[train] 33 34 elapsed_time = time.time() - start 35 36 # モデルを学習 37 model = KNeighborsClassifier(n_neighbors=k) 38 model.fit(train_data, test_data) 39 40 # 一つだけ取り除いたテストデータを識別 41 predicted_label = model.predict(features[test]) 42 predicted_labels.append(predicted_label) 43 44 # 正解率を計算 45 score = accuracy_score(targets, predicted_labels) 46 print('k={}: {}'.format(k, score)) 47 48 accuracy_scores.append(score) 49 50 # 各経過時間を表示 51 print("経過時間:{:.2f}".format(elapsed_time)) 52 53 # 使う近傍数ごとの正解率を折れ線グラフ 54 X = list(ks) 55 plt.plot(X, accuracy_scores) 56 57 plt.xlabel('k') 58 plt.ylabel('正解率') 59 plt.show() 60 61 62if __name__ == '__main__': 63 main()

###補足情報
Anaconda3 Python

levanter76👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

train_test_splitは、分割対象のデータ(例えば1000件)と訓練データと試験データの割合を設定するとその割合でランダムに2つのデータセットを生成します。したがって、分割のコードは以下のようにすると、試験データを30%、訓練データ70%に分割したものになります。

python3

1train_dataX ,test_dataX,train_dataY,test_dataY = model_selection.tarin_test_split(features,targets,test_size=0.3)

訓練には、上記のtarin_dataXとtrain_dataYを使用します。この場合、データを配列のまま訓練を行うことになるのでfor文による繰り返し処理は不要で、上記の配列をそのままmodel.fit()に引数として与えればいいことになります。

python3

1model.fit(train_dataY, train_dataX)

テストには、訓練済のモデルにtest_dataXを引数として与えることで配列全体について結果を返してくれます。あとは、その結果の配列とtest_dataYを比較することで精度の評価ができます。

投稿2017/12/03 09:12

R.Shigemori

総合スコア3376

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

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

退会済みユーザー

退会済みユーザー

2017/12/04 14:16

# データをロード mnist = datasets.fetch_mldata('MNIST original', data_home='data/src/download/') train_dataX ,test_dataX,train_dataY,test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-6-1fcbcb06faa7> in <module>() 2 mnist = datasets.fetch_mldata('MNIST original', data_home='data/src/download/') 3 ----> 4 train_dataX ,test_dataX,train_dataY,test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) NameError: name 'features' is not defined となってしまう。
退会済みユーザー

退会済みユーザー

2017/12/04 14:18

ちなみに、model.fit(train_dataY, train_dataX) でも、使う近傍数ごとの正解率を折れ線グラフはできますか
R.Shigemori

2017/12/04 14:34

> NameError: name 'features' is not defined 『# 特徴データとラベルデータを取り出す』となっているコードでfeaturesとtargetsを定義しているので、そのあとでなければnot definedになります。 > 使う近傍数ごとの正解率を折れ線グラフはできますか できます。 近傍数を変更したモデルの定義は、model = KNeighborsClassifier(n_neighbors=k)の部分で行っています。model.fit()はこのモデルにデータを与えて学習させているだけです。OneLeaveOutからtrain_test_splitに変更した場合は、学習用データの件数が異なるだけなので処理そのものには影響しません。
退会済みユーザー

退会済みユーザー

2017/12/04 14:55

def main(): # 特徴データとラベルデータを取り出す features = mnist.data targets = mnist.target train_dataX ,test_dataX,train_dataY,test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) # 検証する近傍数 K = 10 ks = range(1, K + 1) # 使う近傍数ごとに正解率&各経過時間を計算 accuracy_scores = [] start = time.time() model.fit(train_dataY, train_dataX) elapsed_time = time.time() - start # モデルを学習 model = KNeighborsClassifier(n_neighbors=k) model.fit(train_data, test_data) # 一つだけ取り除いたテストデータを識別 predicted_label = model.predict(features[test]) predicted_labels.append(predicted_label) # 正解率を計算 score = accuracy_score(targets, predicted_labels) print('k={}: {}'.format(k, score)) accuracy_scores.append(score) # 各経過時間を表示 print("経過時間:{:.2f}".format(elapsed_time)) # 使う近傍数ごとの正解率を折れ線グラフ X = list(ks) plt.plot(X, accuracy_scores) plt.xlabel('k') plt.ylabel('正解率') plt.show() if __name__ == '__main__': main() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-4-4d2c413c4065> in <module>() 47 48 if __name__ == '__main__': ---> 49 main() <ipython-input-4-4d2c413c4065> in main() 16 start = time.time() 17 ---> 18 model.fit(train_dataY, train_dataX) 19 20 elapsed_time = time.time() - start UnboundLocalError: local variable 'model' referenced before assignment これは、clf = svm.SVC() のようにmodelもあるのでしょうか
R.Shigemori

2017/12/04 23:49

エラーメッセージはモデルの定義がない、というものです。コードを見るとstart=のあとにmodel.fitがあります。 なお、このままだと近傍数を入れ替えた繰り返し処理になっていないので、K=10の結果しか得られません。元コードに存在した近傍数を入れ替えた繰り返しを追加したほうがいいでしょう
退会済みユーザー

退会済みユーザー

2017/12/05 16:54

def main(): # 特徴データとラベルデータを取り出す features = mnist.data targets = mnist.target train_dataX ,test_dataX,train_dataY,test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) # 検証する近傍数 K = 10 ks = range(1, K + 1) # 使う近傍数ごとに正解率&各経過時間を計算 accuracy_scores = [] start = time.time() for k in ks: predicted_labels = [] loo = LeaveOneOut() for train, test in loo.split(features): train_data = features[train] test_data = targets[train] elapsed_time = time.time() - start # モデルを学習 model = KNeighborsClassifier(n_neighbors=k) model.fit(train_dataY, train_dataX) # 一つだけ取り除いたテストデータを識別 predicted_label = model.predict(features[test]) predicted_labels.append(predicted_label) # 正解率を計算 score = accuracy_score(targets, predicted_labels) print('k={}: {}'.format(k, score)) accuracy_scores.append(score) # 各経過時間を表示 print("経過時間:{:.2f}".format(elapsed_time)) # 使う近傍数ごとの正解率を折れ線グラフ X = list(ks) plt.plot(X, accuracy_scores) plt.xlabel('k') plt.ylabel('正解率') plt.show() if __name__ == '__main__': main() # 使う近傍数ごとに正解率&各経過時間を計算をする ところの書き換えがよく分かりません。おしえてください。
R.Shigemori

2017/12/05 22:13

正確にいうと、オリジナルコードで実装済みだった部分を元に戻せばいいことになりますので、『よく分かりません』というのはどういう意味なのかもう少し詳しく教えてください。
退会済みユーザー

退会済みユーザー

2017/12/06 08:59

for k in ks: predicted_labels = [] loo = LeaveOneOut() for train, test in loo.split(features): train_data = features[train] test_data = targets[train] ココの【loo = LeaveOneOut()】はlooのままでいいのでしょうか?
R.Shigemori

2017/12/06 11:08

train_test_splitを使ってテストデータを生成しているのでLeaveOneOutを使ってテストデータを生成するコードとそれを用いたテストの繰り返しは不要となります。 train_test_splitは、1件単位でテストデータを生成する代わりにあらかじめ指定した割合に相当する件数のデータが配列として生成されるので、テストも配列単位で実行することができます。
退会済みユーザー

退会済みユーザー

2017/12/06 14:22

def main(): # 特徴データとラベルデータを取り出す features = mnist.data targets = mnist.target train_dataX ,test_dataX,train_dataY,test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) # 検証する近傍数 K = 10 ks = range(1, K + 1) # 使う近傍数ごとに正解率&各経過時間を計算 accuracy_scores = [] start = time.time() for k in ks: predicted_labels = [] elapsed_time = time.time() - start # モデルを学習 model = KNeighborsClassifier(n_neighbors=k) model.fit(train_dataY, train_dataX) # 一つだけ取り除いたテストデータを識別 predicted_label = model.predict(features[test]) predicted_labels.append(predicted_label) # 正解率を計算 score = accuracy_score(targets, predicted_labels) print('k={}: {}'.format(k, score)) accuracy_scores.append(score) # 各経過時間を表示 print("経過時間:{:.2f}".format(elapsed_time)) # 使う近傍数ごとの正解率を折れ線グラフ X = list(ks) plt.plot(X, accuracy_scores) plt.xlabel('k') plt.ylabel('正解率') plt.show() if __name__ == '__main__': main() これで実行してもなにも起きないのはなぜですか
R.Shigemori

2017/12/07 15:01

簡単にデバッグしたところ、ミスがあるようです。 model.fit(train_dataY,train_dataX) --> model.fit(train_dataX,train_dataY) fit()メソッドは、特徴量・ラベルの順で設定する必要があります。 predicted_label = model.predict(features[test]) --> predicted_label = model.predict(test_dataX) One_Leave_Outを使用したときのものが残っているようです。今回はtest_dataXがテスト対象データセットなのでこれを使うことになります。 predicted_labels.append(predicted_label) --> コメントアウト これも以前のコードが残っているようです。今回の場合、複数件を一括で処理しているので、その結果は配列の状態で返ってきます。 score = accuracy_score(targets, predicted_labels) --> score = accuracy_score(targets, predicted_label) 上記で示した通り、accuracy_score()にセットする予測ラベルはpredictの戻り値(predict_label)なので、修正が必要そうです。 ただし、何も起きない理由はよくわかりません。通常ならエラーが出ると思うのですが…
退会済みユーザー

退会済みユーザー

2017/12/08 10:02 編集

if __name__ == '__main__': main()
退会済みユーザー

退会済みユーザー

2017/12/08 10:30

def main(): # 特徴データとラベルデータを取り出す features = mnist.data targets = mnist.target train_dataX, test_dataX, train_dataY, test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) # 検証する近傍数 K = 10 ks = range(1, K + 1) # 使う近傍数ごとに正解率&各経過時間を計算 accuracy_scores = [] start = time.time() for k in ks: predicted_labels = [] elapsed_time = time.time() - start # モデルを学習 model = KNeighborsClassifier(n_neighbors=k, metric='euclidean') model.fit(train_dataX,train_dataY) # 一つだけ取り除いたテストデータを識別 predicted_label = model.predict(test_dataX) # 正解率を計算 score = accuracy_score(targets, predicted_label) print('k={}: {}'.format(k, score)) accuracy_scores.append(score) # 各経過時間を表示 print("経過時間:{:.2f}".format(elapsed_time)) # 使う近傍数ごとの正解率を折れ線グラフ X = list(ks) plt.plot(X, accuracy_scores) plt.xlabel('k') plt.ylabel('正解率') plt.show() if __name__ == '__main__': main()
退会済みユーザー

退会済みユーザー

2017/12/08 10:31

実行したところ --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-4-a49f56a69ab6> in <module>() 45 46 if __name__ == '__main__': ---> 47 main() <ipython-input-4-a49f56a69ab6> in main() 27 28 # 正解率を計算 ---> 29 score = accuracy_score(targets, predicted_label) 30 print('k={}: {}'.format(k, score)) 31 ~\Anaconda3\lib\site-packages\sklearn\metrics\classification.py in accuracy_score(y_true, y_pred, normalize, sample_weight) 174 175 # Compute accuracy for each possible representation --> 176 y_type, y_true, y_pred = _check_targets(y_true, y_pred) 177 if y_type.startswith('multilabel'): 178 differing_labels = count_nonzero(y_true - y_pred, axis=1) ~\Anaconda3\lib\site-packages\sklearn\metrics\classification.py in _check_targets(y_true, y_pred) 69 y_pred : array or indicator matrix 70 """ ---> 71 check_consistent_length(y_true, y_pred) 72 type_true = type_of_target(y_true) 73 type_pred = type_of_target(y_pred) ~\Anaconda3\lib\site-packages\sklearn\utils\validation.py in check_consistent_length(*arrays) 202 if len(uniques) > 1: 203 raise ValueError("Found input variables with inconsistent numbers of" --> 204 " samples: %r" % [int(l) for l in lengths]) 205 206 ValueError: Found input variables with inconsistent numbers of samples: [70000, 21000]
退会済みユーザー

退会済みユーザー

2017/12/08 10:31

どのように改善したらいいですか。
R.Shigemori

2017/12/08 11:16

見逃しがありましたね。 エラーは、正解率を求める教師側のラベルと予測結果のラベルで数は不一致という意味です。予測は全件のうちtrain_test_splitで分割したものを用いているので、教師側にもそれに対応するものを用いる必要があります。
退会済みユーザー

退会済みユーザー

2017/12/08 15:01

それはどのようにすればよいですか
R.Shigemori

2017/12/08 17:54

どうすればいいとお考えでしょうか? train_test_splitのコードが書けている以上、理解されていると思います
退会済みユーザー

退会済みユーザー

2017/12/09 11:48

def main(): # 特徴データとラベルデータを取り出す features = mnist.data targets = mnist.target train_dataX, test_dataX, train_dataY, test_dataY = model_selection.train_test_split(features,targets,test_size=0.3) # 検証する近傍数 K = 10 ks = range(1, K + 1) # 使う近傍数ごとに正解率&各経過時間を計算 accuracy_scores = [] start = time.time() for k in ks: predicted_labels = [] elapsed_time = time.time() - start # モデルを学習 model = KNeighborsClassifier(n_neighbors=k, metric='euclidean') model.fit(train_dataX,train_dataY) # 一つだけ取り除いたテストデータを識別 predicted_label = model.predict(test_dataX) # 正解率を計算 score = accuracy_score(test_dataY, predicted_label) print('k={}: {}'.format(k, score)) accuracy_scores.append(score) # 各経過時間を表示 print("経過時間:{:.2f}".format(elapsed_time)) # 使う近傍数ごとの正解率を折れ線グラフ X = list(ks) plt.plot(X, accuracy_scores) plt.xlabel('k') plt.ylabel('正解率') plt.show() if __name__ == '__main__': main() これでできました!けど、時間かかってしまうのはしょうがないですよね?
R.Shigemori

2017/12/09 12:46

時間がかかるというのは、オリジナルコードと比較してという意味でしょうか?オリジナルコードは、データ件数×10回の繰り返し処理が必要でしたが、上記コードは10回の繰り返し処理で済むのでスピードアップにつながることが期待できました。ただし、1回で処理対象となるデータがオリジナルコードが1件に対して上記コードは全件×0.3と大幅像なのでスピードダウンの要因になりえます。 最終的にどうなるのかはデータに依存する部分も多いので、結果を見てから考えるしかないように思います
退会済みユーザー

退会済みユーザー

2017/12/09 13:19

ありがとうございました。
guest

0

Leave-One-Outだと、1万件を対象にすると1万回の学習と1万回のテストを行うことになるので非常に時間がかかります。したがって、今のテストデータ・トレーニングデータの生成方法であるLeaveOneOutをtrain_test_splitに変えると、テストデータとトレーニングデータを指定した割合で分割するので、そのまま学習と試験をすることで、1回の処理でそれなりの件数の試験ができます。

投稿2017/12/02 00:23

R.Shigemori

総合スコア3376

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

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

退会済みユーザー

退会済みユーザー

2017/12/02 06:23

LeaveOneOutをtrain_test_splitに変えたのですが、どのようにテストデータとトレーニングデータを指定すればよろしいでしょうか。
退会済みユーザー

退会済みユーザー

2017/12/02 07:08

train_size = 500 test_size = 100 train_data, test_data, train_label, test_label = model_selection.train_test_split(mnist.data, mnist.target, test_size=test_size, train_size=train_size) このように書いたのですが(合っていますかね・・・) for k in ks: predicted_labels = [] loo = LeaveOneOut() for train, test in loo.split(features): train_data = features[train] test_data = targets[train] この部分(loo)をどうすればよいか教えて下さい
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問