CNTK入門05:手書き識別ピクチャを分類するための全接続フィードフォワードモデル
CNTK入門05:手書き識別ピクチャを分類するための全接続フィードフォワードモデル
------- A fully connected feed-forward model for classification of MNIST images.
1. .ExamplesImageDataSetsMNISTの下に2つのファイルがあり、Python install_を実行します.mnist.py手書き認識画像をダウンロードします.
このうち60000は試験訓練データ、10000枚は試験データとした.
コード:install_mnist.py
上のメイン関数は、mnist_というファイルの関数を呼び出します.utils.py
目次\Examples\Image\Classification\MLP\Python\SimpleMNIST.pyは手書きで識別するプログラムです.
Python SimpleMNIST.pyを実行します.
----------------------------------------------------------------------------------------------------------------------------
付録:
1. os.chdir()#現在の作業ディレクトリを指定したパスに変更
2.np.hstack()の解釈:stack()Join a sequence of arrays along a new axis.hstack() Stack arrays in sequence horizontally (column wise). dstack() Stack arrays in sequence depth wise (along third dimension). concatenate() Join a sequence of arrays along an existing axis. vsplit () Split array into a list of multiple sub-arrays vertically. 2.1 stack():新しい軸で2つの配列を接続します.
np.random.randn(3,4)は、標準正規分布に従う3行4列の行列を返します.
2.2 numpy.hstack()関数
関数プロトタイプ:numpy.hstack(tup)
ここでtupはarraysシーケンス、The arrays must have the same shape、except in the dimensioncorresponding to axis(the first、by default).
等価:np.concatenate(tup, axis=1)
numpy.vstack()関数
関数プロトタイプ:numpy.vstack(tup)
等価:np.concatenate(tup, axis=0) if tup contains arrays thatare at least 2-dimensional.
プログラムの例:
2.4 numpy.dstack()関数
関数プロトタイプ:numpy.dstack(tup)
等価:np.concatenate(tup, axis=2)
プログラムの例:
2.5 numpy.concatenate()関数
関数プロトタイプ:numpy.concatenate((a1, a2, ...), axis=0)
プログラムの例:
2.6 numpy.vsplit()関数
関数プロトタイプ:numpy.vsplit(ary, indices_or_sections)
プログラムの例:
------------------------------------------------------------------------------------
3.url.urlretrieve(filename[,reporthook[,data]]]))の使用
urllib.urlretrieve(url,filename)はネットワークファイルをダウンロードし、最初の要素はターゲットurlであり、2番目のパラメータは保存されたファイルの絶対パス(ファイル名を含む)であり、戻り値はtuple(filename,header)であり、filenameはローカルに保存されたパスを表し、headerはサーバの応答ヘッダを表す.urlretrieveに1つのパラメータしか指定されていない場合、返される値のfilenameは生成された一時ファイル名であり、関数の実行が完了するとその一時ファイルはパラメータを削除されます.パラメータreporthookはコールバック関数であり、サーバに接続し、対応するデータブロックの転送が完了するとコールバックがトリガーされます.コールバック関数名は任意ですが、パラメータは3つでなければなりません.一般的にreporthook(block_read,block_size,total_size)を直接使用してコールバック関数を定義し、block_sizeは、読み出すたびにブロックのサイズ、block_readは、読み出すたびのデータブロック数、taotal_sizeは合計で読み込まれたデータ量で、単位はbyteです.reporthook関数を使用して、読み取りの進捗状況を表示できます.
------- A fully connected feed-forward model for classification of MNIST images.
1. .ExamplesImageDataSetsMNISTの下に2つのファイルがあり、Python install_を実行します.mnist.py手書き認識画像をダウンロードします.
このうち60000は試験訓練データ、10000枚は試験データとした.
コード:install_mnist.py
from __future__ import print_function
import os
import mnist_utils as ut
if __name__ == "__main__":
#
os.chdir(os.path.abspath(os.path.dirname(__file__)))
train = ut.load('http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz',
'http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz', 60000)
print ('Writing train text file...')
ut.savetxt(r'./Train-28x28_cntk_text.txt', train)
print ('Done.')
test = ut.load('http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz',
'http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz', 10000)
print ('Writing test text file...')
ut.savetxt(r'./Test-28x28_cntk_text.txt', test)
print ('Done.')
上のメイン関数は、mnist_というファイルの関数を呼び出します.utils.py
from __future__ import print_function
try:
from urllib.request import urlretrieve
except ImportError:
from urllib import urlretrieve
import sys
import gzip
import shutil
import os
import struct
import numpy as np
def loadData(src, cimg):
print ('Downloading ' + src)
#retrieve, ;src ,./delete.me ; tuple(filename,header)
#filename ,header
gzfname, h = urlretrieve(src, './delete.me')
print ('Done.')
try:
with gzip.open(gzfname) as gz:
# (fmt) string, tuple
n = struct.unpack('I', gz.read(4))
# Read magic number.
if n[0] != 0x3080000:
raise Exception('Invalid file: unexpected magic number.')
# Read number of entries.
n = struct.unpack('>I', gz.read(4))[0]
if n != cimg:
raise Exception('Invalid file: expected {0} entries.'.format(cimg))
crow = struct.unpack('>I', gz.read(4))[0]
ccol = struct.unpack('>I', gz.read(4))[0]
if crow != 28 or ccol != 28:
raise Exception('Invalid file: expected 28 rows/cols per image.')
# Read data.
res = np.fromstring(gz.read(cimg * crow * ccol), dtype = np.uint8)
finally:
os.remove(gzfname)
return res.reshape((cimg, crow * ccol))
def loadLabels(src, cimg):
print ('Downloading ' + src)
gzfname, h = urlretrieve(src, './delete.me')
print ('Done.')
try:
with gzip.open(gzfname) as gz:
n = struct.unpack('I', gz.read(4))
# Read magic number.
if n[0] != 0x1080000:
raise Exception('Invalid file: unexpected magic number.')
# Read number of entries.
n = struct.unpack('>I', gz.read(4))
if n[0] != cimg:
raise Exception('Invalid file: expected {0} rows.'.format(cimg))
# Read labels.
res = np.fromstring(gz.read(cimg), dtype = np.uint8)
finally:
os.remove(gzfname)
return res.reshape((cimg, 1))# cimg ,1
# : , ,
def load(dataSrc, labelsSrc, cimg):
data = loadData(dataSrc, cimg)
labels = loadLabels(labelsSrc, cimg)
#
return np.hstack((data, labels))
def savetxt(filename, ndarray):
with open(filename, 'w') as f:
labels = list(map(' '.join, np.eye(10, dtype=np.uint).astype(str)))
for row in ndarray:
row_str = row.astype(str)
label_str = labels[row[-1]]
feature_str = ' '.join(row_str[:-1])
f.write('|labels {} |features {}
'.format(label_str, feature_str))
目次\Examples\Image\Classification\MLP\Python\SimpleMNIST.pyは手書きで識別するプログラムです.
Python SimpleMNIST.pyを実行します.
import argparse
import numpy as np
import sys
import os
from cntk.train import Trainer, minibatch_size_schedule
from cntk.io import MinibatchSource, CTFDeserializer, StreamDef, StreamDefs, INFINITELY_REPEAT
from cntk.device import cpu, try_set_default_device
from cntk.learners import adadelta, learning_rate_schedule, UnitType
from cntk.ops import input, relu, element_times, constant
from cntk.losses import cross_entropy_with_softmax
from cntk.metrics import classification_error
from cntk.train.training_session import *
from cntk.logging import ProgressPrinter, TensorBoardProgressWriter
abs_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(abs_path, "..", "..", "..", "..", "common"))
from nn import fully_connected_classifier_net
def check_path(path):
if not os.path.exists(path):
readme_file = os.path.normpath(os.path.join(
os.path.dirname(path), "..", "README.md"))
raise RuntimeError(
"File '%s' does not exist. Please follow the instructions at %s to download and prepare it." % (path, readme_file))
def create_reader(path, is_training, input_dim, label_dim):
return MinibatchSource(CTFDeserializer(path, StreamDefs(
features = StreamDef(field='features', shape=input_dim, is_sparse=False),
labels = StreamDef(field='labels', shape=label_dim, is_sparse=False)
)), randomize=is_training, max_sweeps = INFINITELY_REPEAT if is_training else 1)
# Creates and trains a feedforward classification model for MNIST images
def simple_mnist(tensorboard_logdir=None):
input_dim = 784
num_output_classes = 10
num_hidden_layers = 1
hidden_layers_dim = 200
# Input variables denoting the features and label data
feature = input(input_dim, np.float32)
label = input(num_output_classes, np.float32)
# Instantiate the feedforward classification model
scaled_input = element_times(constant(0.00390625), feature)
z = fully_connected_classifier_net(
scaled_input, num_output_classes, hidden_layers_dim, num_hidden_layers, relu)
ce = cross_entropy_with_softmax(z, label)
pe = classification_error(z, label)
data_dir = os.path.join(abs_path, "..", "..", "..", "DataSets", "MNIST")
path = os.path.normpath(os.path.join(data_dir, "Train-28x28_cntk_text.txt"))
check_path(path)
reader_train = create_reader(path, True, input_dim, num_output_classes)
input_map = {
feature : reader_train.streams.features,
label : reader_train.streams.labels
}
# Training config
minibatch_size = 64
num_samples_per_sweep = 60000
num_sweeps_to_train_with = 10
# Instantiate progress writers.
#training_progress_output_freq = 100
progress_writers = [ProgressPrinter(
#freq=training_progress_output_freq,
tag='Training',
num_epochs=num_sweeps_to_train_with)]
if tensorboard_logdir is not None:
progress_writers.append(TensorBoardProgressWriter(freq=10, log_dir=tensorboard_logdir, model=z))
# Instantiate the trainer object to drive the model training
trainer = Trainer(z, (ce, pe), adadelta(z.parameters), progress_writers)
training_session(
trainer=trainer,
mb_source = reader_train,
mb_size = minibatch_size,
model_inputs_to_streams = input_map,
max_samples = num_samples_per_sweep * num_sweeps_to_train_with,
progress_frequency=num_samples_per_sweep
).train()
# Load test data
path = os.path.normpath(os.path.join(data_dir, "Test-28x28_cntk_text.txt"))
check_path(path)
reader_test = create_reader(path, False, input_dim, num_output_classes)
input_map = {
feature : reader_test.streams.features,
label : reader_test.streams.labels
}
# Test data for trained model
test_minibatch_size = 1024
num_samples = 10000
num_minibatches_to_test = num_samples / test_minibatch_size
test_result = 0.0
for i in range(0, int(num_minibatches_to_test)):
mb = reader_test.next_minibatch(test_minibatch_size, input_map=input_map)
eval_error = trainer.test_minibatch(mb)
test_result = test_result + eval_error
# Average of evaluation errors of all test minibatches
return test_result / num_minibatches_to_test
if __name__=='__main__':
# Specify the target device to be used for computing, if you do not want to
# use the best available one, e.g.
# try_set_default_device(cpu())
parser = argparse.ArgumentParser()
parser.add_argument('-tensorboard_logdir', '--tensorboard_logdir',
help='Directory where TensorBoard logs should be created', required=False, default=None)
args = vars(parser.parse_args())
error = simple_mnist(args['tensorboard_logdir'])
print("Error: %f" % error)
----------------------------------------------------------------------------------------------------------------------------
付録:
1. os.chdir()#現在の作業ディレクトリを指定したパスに変更
2.np.hstack()の解釈:stack()Join a sequence of arrays along a new axis.hstack() Stack arrays in sequence horizontally (column wise). dstack() Stack arrays in sequence depth wise (along third dimension). concatenate() Join a sequence of arrays along an existing axis. vsplit () Split array into a list of multiple sub-arrays vertically. 2.1 stack():新しい軸で2つの配列を接続します.
>>> arrays = [np.random.randn(3, 4) for _ in range(10)]
>>> np.stack(arrays, axis=0).shape
(10, 3, 4)
>>> np.stack(arrays, axis=1).shape
(3, 10, 4)
>>> np.stack(arrays, axis=2).shape
(3, 4, 10)
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 3, 4])
>>> np.stack((a, b))
array([[1, 2, 3],
[2, 3, 4]])
>>> np.stack((a, b), axis=-1)
array([[1, 2],
[2, 3],
[3, 4]])
np.random.randn(3,4)は、標準正規分布に従う3行4列の行列を返します.
2.2 numpy.hstack()関数
関数プロトタイプ:numpy.hstack(tup)
ここでtupはarraysシーケンス、The arrays must have the same shape、except in the dimensioncorresponding to axis(the first、by default).
等価:np.concatenate(tup, axis=1)
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.hstack((a,b))
array([1, 2, 3, 2, 3, 4])
>>> a = np.array([[1],[2],[3]])
>>> b = np.array([[2],[3],[4]])
>>> np.hstack((a,b))
array([[1, 2],
[2, 3],
[3, 4]])
2.3 numpy.vstack()関数
関数プロトタイプ:numpy.vstack(tup)
等価:np.concatenate(tup, axis=0) if tup contains arrays thatare at least 2-dimensional.
プログラムの例:
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 3, 4])
>>> np.vstack((a,b))
array([[1, 2, 3],
[2, 3, 4]])
>>> a = np.array([[1], [2], [3]])
>>> b = np.array([[2], [3], [4]])
>>> np.vstack((a,b))
array([[1],
[2],
[3],
[2],
[3],
[4]])
2.4 numpy.dstack()関数
関数プロトタイプ:numpy.dstack(tup)
等価:np.concatenate(tup, axis=2)
プログラムの例:
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.dstack((a,b))
array([[[1, 2],
[2, 3],
[3, 4]]])
>>>
>>> a = np.array([[1],[2],[3]])
>>> b = np.array([[2],[3],[4]])
>>> np.dstack((a,b))
array([[[1, 2]],
[[2, 3]],
[[3, 4]]])
2.5 numpy.concatenate()関数
関数プロトタイプ:numpy.concatenate((a1, a2, ...), axis=0)
プログラムの例:
>>> a = np.array([[1, 2], [3, 4]])
>>> b = np.array([[5, 6]])
>>> np.concatenate((a, b), axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
>>> np.concatenate((a, b.T), axis=1)
array([[1, 2, 5],
[3, 4, 6]])
This function will not preserve masking of MaskedArray inputs.
>>>
>>> a = np.ma.arange(3)
>>> a[1] = np.ma.masked
>>> b = np.arange(2, 5)
>>> a
masked_array(data = [0 -- 2],
mask = [False True False],
fill_value = 999999)
>>> b
array([2, 3, 4])
>>> np.concatenate([a, b])
masked_array(data = [0 1 2 2 3 4],
mask = False,
fill_value = 999999)
>>> np.ma.concatenate([a, b])
masked_array(data = [0 -- 2 2 3 4],
mask = [False True False False False False],
fill_value = 999999)
2.6 numpy.vsplit()関数
関数プロトタイプ:numpy.vsplit(ary, indices_or_sections)
プログラムの例:
>>> x = np.arange(16.0).reshape(4, 4)
>>> x
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 12., 13., 14., 15.]])
>>> np.vsplit(x, 2)
[array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.]]),
array([[ 8., 9., 10., 11.],
[ 12., 13., 14., 15.]])]
>>> np.vsplit(x, np.array([3, 6]))
[array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]),
array([[ 12., 13., 14., 15.]]),
array([], dtype=float64)]
With a higher dimensional array the split is still along the first axis.
>>>
>>> x = np.arange(8.0).reshape(2, 2, 2)
>>> x
array([[[ 0., 1.],
[ 2., 3.]],
[[ 4., 5.],
[ 6., 7.]]])
>>> np.vsplit(x, 2)
[array([[[ 0., 1.],
[ 2., 3.]]]),
array([[[ 4., 5.],
[ 6., 7.]]])]
------------------------------------------------------------------------------------
3.url.urlretrieve(filename[,reporthook[,data]]]))の使用
urllib.urlretrieve(url,filename)はネットワークファイルをダウンロードし、最初の要素はターゲットurlであり、2番目のパラメータは保存されたファイルの絶対パス(ファイル名を含む)であり、戻り値はtuple(filename,header)であり、filenameはローカルに保存されたパスを表し、headerはサーバの応答ヘッダを表す.urlretrieveに1つのパラメータしか指定されていない場合、返される値のfilenameは生成された一時ファイル名であり、関数の実行が完了するとその一時ファイルはパラメータを削除されます.パラメータreporthookはコールバック関数であり、サーバに接続し、対応するデータブロックの転送が完了するとコールバックがトリガーされます.コールバック関数名は任意ですが、パラメータは3つでなければなりません.一般的にreporthook(block_read,block_size,total_size)を直接使用してコールバック関数を定義し、block_sizeは、読み出すたびにブロックのサイズ、block_readは、読み出すたびのデータブロック数、taotal_sizeは合計で読み込まれたデータ量で、単位はbyteです.reporthook関数を使用して、読み取りの進捗状況を表示できます.