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

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

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

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

Q&A

解決済

1回答

4151閲覧

Python 2.7.12, mnistデータをk-nnで識別しエラー率を算出する方法

3naoki

総合スコア12

Python

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

0グッド

0クリップ

投稿2016/10/31 17:54

下記URLのサイトにある4つのmnistデータをk-nnで識別しエラー率を算出したいと考えています。他の方の方法を参考にコードを書いてみたのですがエラーが出てしまいました。アドバイス頂けると幸いです。

http://yann.lecun.com/exdb/mnist/

以下mnistデータの読み込み及び識別プログラム

Python

1import struct 2import numpy as np 3 4 5class MNIST: 6 def __init__(self, LT): 7 8 if LT == 'L': 9 self.fnLabel = 'train-labels.idx1-ubyte' 10 self.fnImage = 'train-images.idx3-ubyte' 11 else: 12 self.fnLabel = 't10k-labels.idx1-ubyte' 13 self.fnImage = 't10k-images.idx3-ubyte' 14 15 def getLabel(self): 16 17 return readLabel ( self.fnLabel ) 18 19 def getImage(self): 20 return readImage(self.fnImage) 21 22 23##### reading the label file 24# 25def readLabel(fnLabel): 26 f = open ( fnLabel, 'r' ) 27 28 ### header (two 4B integers, magic number(2049) & number of items) 29 # 30 header = f.read ( 8 ) 31 mn, num = struct.unpack ( '>2i', header ) # MSB first (bigendian) 32 assert mn == 2049 33 # print mn, num 34 35 ### labels (unsigned byte) 36 # 37 label = np.array ( struct.unpack ( '>%dB' % num, f.read ( ) ), dtype=int ) 38 39 f.close ( ) 40 41 return label 42 43 44##### reading the image file 45# 46def readImage(fnImage): 47 f = open ( fnImage, 'r' ) 48 49 ### header (four 4B integers, magic number(2051), #images, #rows, and #cols 50 # 51 header = f.read ( 16 ) 52 mn, num, nrow, ncol = struct.unpack ( '>4i', header ) # MSB first (bigendian) 53 assert mn == 2051 54 # print mn, num, nrow, ncol 55 56 ### pixels (unsigned byte) 57 # 58 pixel = np.empty ( (num, nrow, ncol) ) 59 npixel = nrow * ncol 60 for i in range ( num ): 61 buf=struct.unpack('>%dB'%npixel,f.read(npixel)) 62 pixel[ i, :, : ] = np.asarray ( buf ).reshape ( (nrow, ncol) ) 63 64 f.close ( ) 65 66 return pixel 67 68 69if __name__ == '__main__': 70 print '# MNIST training data' 71 mnist = MNIST ( 'L' ) 72 lab = mnist.getLabel ( ) 73 dat = mnist.getImage ( ) 74 print lab.shape, dat.shape 75 76 print '# MNIST test data' 77 mnist = MNIST ( 'T' ) 78 lab = mnist.getLabel ( ) 79 dat = mnist.getImage ( ) 80 print lab.shape, dat.shape

以下エラー率の算出

Python

1import numpy as np 2import mnist1 as mnist 3 4##### training data 5# 6mn = mnist.MNIST('L') 7labL = mn.getLabel() 8nL = labL.shape[0] 9xL = mn.getImage().reshape((nL, -1)) 10print '# xL: ', xL.shape 11 12##### test data 13# 14mn = mnist.MNIST('T') 15labT = mn.getLabel() 16nT = labT.shape[0] 17xT = mn.getImage().reshape((nT, -1)) 18print '# xT: ', xT.shape 19 20##### nearest neighbor classification 21# 22xLsq = np.sum(xL ** 2, axis=1) 23out = np.empty(nT, dtype=int) 24for i in range(nT): 25 if i % 1000 == 0: 26 print i 27 d = -2 * np.dot(xL, xT[i, :]) + xLsq 28 out[i] = labL[np.argmin(d)] 29 30er = np.sum(out != labT) / float(nT) 31 32print '# test error rate = ', er * 100, '%'

下記プログラムのエラー

Traceback (most recent call last):
File "C:/.../mnisterror.py", line 9, in <module>
xL = mn.getImage().reshape((nL, -1))
File "C:...\mnist1.py", line 20, in getImage
return readImage(self.fnImage)
File "C:...\mnist1.py", line 61, in readImage
buf=struct.unpack('>%dB'%npixel,f.read(npixel))
struct.error: unpack requires a string argument of length 784

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

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

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

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

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

guest

回答1

0

ベストアンサー

unpack requires a string argument of length 784

エラーメッセージは、unpack するデータの長さが足りていないようです。

原因は恐らくファイルの open の mode
ファイルの open の第二引数を 'rb' として、バイナリーモードで開いてみてください。
デフォルトだとテキストモードで読み込まれ、windows では改行コードが変換されてしまいます。

struct.unpack('>%dB'%npixel, f.read(npixel))

ここで unpackのサイズを動的に指定していますが、ファイルがテキストモードで開かれている場合
len(f.read(npixel)) == npixel が真となるとは限りません。
struct.unpack が要求するデータ長を f.read が返さなかった時、上記のエラーとなります。

また、該当箇所のコードでは、unpackでPythonの数値のリストを一時的に生成し
numpy の配列を再構築といったことをしていますが、numpy で直接読み込むほうが効率良いので
より規模の大きなデータを扱う場合や、速度を求められる場合等は、
np.fromfile や np.memmap の利用を検討してみてください。

参考までに, np.memmap を使う場合

python

1pixel = np.memmap(filename, ">B", mode="r", offset=16, shape=(num, nrow, ncol))

投稿2016/10/31 21:06

teamikl

総合スコア8664

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

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

3naoki

2016/10/31 23:08

ご丁寧にご回答頂きありがとうございます。 ご指摘頂いた通り、ファイルの open の mode に問題がありrbにすることで解決しました。 ただ計算に若干時間かかるのでnp.memmap を試してみたのですがエラー率がおかしな値になってしまいました。 恐らく自分の理解が足りておらず直し方が違ったのだと思いますが、何かアドバス頂けると幸いです 下記修正箇所です #pixel = np.empty ( (num, nrow, ncol) ) #npixel = nrow * ncol #for i in range ( num ): #buf=struct.unpack('>%dB'%npixel,f.read(npixel)) #pixel[ i, :, : ] = np.asarray ( buf ).reshape ( (nrow, ncol) ) #f.close ( ) をご教授頂いたものに変更しました pixel = np.memmap(f, ">B", mode="r", offset=16, shape=(num, nrow, ncol))
teamikl

2016/11/01 05:17

すいません、勝手に持ってきた変数の説明が不足してました。ファイル名の文字列を意図してましたが、 変数 f からヘッダを読み込んだ後に続けて読むなら offset指定(ヘッダの16バイト読み飛ばし)は不要になります
teamikl

2016/11/01 09:20

補足です。エラー箇所しか見ていなかったので、前後の処理まで考慮してませんでした。 f は close されるので、memmap側にファイルのopenを任せたほうがいいかもしれません。 np(f.name, dtype="uint8", offset=16, shape=(num, nrow, ncol)) もう一点懸念があるとすれば、データ型の違いで 元のコードは uint8 で読み込んだものを dtype=float の配列に代入してます。 .astype(float) で型変換出来ます。 ちなみに、byteorder ですが、私も ">B" と書いてしまいましたが、 byte型の場合は読み込み順序には影響しません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問