EeBlog(テクニカルブログ)

AI(人工知能)実践 第7回 TensorFlow(アヤメの分類)2

AI(人工知能)実践 第7回です。
第6回の続きでソースの解説です。
 

第6回で記載したソース全文

import pandas as pd
import os
import urllib

import tensorflow as tf
import numpy as np

IRIS_TRAINING = "iris_training.csv"
IRIS_TRAINING_URL = "http://download.tensorflow.org/data/iris_training.csv"

IRIS_TEST = "iris_test.csv"
IRIS_TEST_URL = "http://download.tensorflow.org/data/iris_test.csv"

#データファイルが無い場合ダウンロード
if not os.path.exists(IRIS_TRAINING):
    raw = urllib.urlopen(IRIS_TRAINING_URL).read()
    with open(IRIS_TRAINING,'w') as f:
        f.write(raw)

if not os.path.exists(IRIS_TEST):
    raw = urllib.urlopen(IRIS_TEST_URL).read()
    with open(IRIS_TEST,'w') as f:
        f.write(raw)
    
#データ読み込み用のメソッド作成
def read_file(file_name):
    data=pd.read_csv(file_name, usecols = [0, 1, 2, 3])
    label = pd.read_csv(file_name, usecols = [4])
    return data.values, label.values

#データ読み込み
training_x, training_y = read_file(IRIS_TRAINING)
test_x, test_y = read_file(IRIS_TEST)

# すべてのfeatureが実数値データであることを指定する
feature_columns = [tf.feature_column.numeric_column("x", shape=[4])]

# 10, 20, 10のノードを持つ3層のDNNを作成
classifier = tf.estimator.DNNClassifier(feature_columns=feature_columns,
                                        hidden_units=[10, 20, 10],
                                        n_classes=3,
                                        model_dir="./iris_model")

# 学習用データ(辞書)を返す関数の作成
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": np.array(training_x)},
    y=np.array(training_y),
    num_epochs=None,
    shuffle=True)

# 学習の実行。stepsを分割して実行しても同様の結果を得られる
classifier.train(input_fn=train_input_fn, steps=2000)

# 評価用データ(辞書)を返す関数の作成
test_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": np.array(test_x)},
    y=np.array(test_y),
    num_epochs=1,
    shuffle=False)

# 評価
accuracy_score = classifier.evaluate(input_fn=test_input_fn)["accuracy"]

print("\nTest Accuracy: {0:f}\n".format(accuracy_score))

第6回では、ダウンロード元・ファイルの変数定義まで解説しましたので、
続きから解説していきます。
 

データ読み込みメソッドの定義

#データ読み込み用のメソッド作成
def read_file(file_name):
    data=pd.read_csv(file_name, usecols = [0, 1, 2, 3])
    label = pd.read_csv(file_name, usecols = [4])
    return data.values, label.values

学習用データと評価用データの2ファイルから読み込むため、
予めデータファイル読み込みのメソッドを定義しています。

自作しているread_fileでは、
ファイル名を引数として受け取り、
受け取ったファイルの1~4カラム目にあるデータと
受け取ったファイルの5カラム目にあるデータを返します。

この際のファイルの読み込みでは、pandas.read_csvを利用しています。
pandas.read_csvは下記のように定義されています。

pandas.read_csv(
filepath_or_buffer, sep=’, ‘, delimiter=None, header=’infer’, names=None,
index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None,
engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False,
skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False,
skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False,
date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression=’infer’,
thousands=None, decimal=b’.’, lineterminator=None, quotechar='”‘, quoting=0, escapechar=None,
comment=None, encoding=None, dialect=None, tupleize_cols=None, error_bad_lines=True,
warn_bad_lines=True, skipfooter=0, doublequote=True, delim_whitespace=False,
low_memory=True, memory_map=False, float_precision=None
)

return : DataFrame or TextParser

よって、下記のソースでは、

data=pd.read_csv(file_name, usecols = [0, 1, 2, 3])

にて、指定されたファイル1行目はヘッダとして扱い、
2行目以降の1~4カラム目(インデックスが0~3になるので数値が異なるように見える)のデータを取得しています。

その次の行に当たる下記ソースでは、指定されたファイルの1行目はヘッダとして扱い、
2行目以降の5カラム目のデータを取得しています。

label = pd.read_csv(file_name, usecols = [4])

feature_columnsの設定

# すべてのfeatureが実数値データであることを指定する
feature_columns = [tf.feature_column.numeric_column("x", shape=[4])]

Estimatorsにデータを渡すための前準備としてfeature colmunの設定をしています。
feature columnとは、生データをEstimatorsで使用出来る形に変換するためのオブジェクトです。
 

DNN(Deep Neural Networks)分類器の作成

# 10, 20, 10のノードを持つ3層のDNNを作成
classifier = tf.estimator.DNNClassifier(feature_columns=feature_columns,
                                        hidden_units=[10, 20, 10],
                                        n_classes=3,
                                        model_dir="./iris_model")

それぞれ10、20、10ノードを持つ3層の隠れ層があり、
ラベル(n_classes)は3つ、モデルの保存先(model_dir)が./iris_modelで
活性化関数がReLUのDeep Neural Networks分類器を作成しています。

tf.estimator.DNNClassifierの初期化メソッドは下記のように定義されています。
詳細は公式サイト(https://www.tensorflow.org/api_docs/python/tf/estimator/DNNClassifier)にて確認してみて下さい。

__init__(
hidden_units, feature_columns,
model_dir=None, n_classes=2,
weight_column=None, label_vocabulary=None,
optimizer=’Adagrad’, activation_fn=tf.nn.relu,
dropout=None, input_layer_partitioner=None,
config=None, warm_start_from=None,
loss_reduction=losses.Reduction.SUM
)
 

Estimatorsに学習用データを渡すための準備

# 学習用データ(辞書)を返す関数の作成
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": np.array(training_x)},
    y=np.array(training_y),
    num_epochs=None,
    shuffle=True)

前述の分類器(tf.estimator.DNNClassifier)では、学習や評価する際に
そのままのデータとラベルを受け取るのではなく、データとラベルを辞書で返す関数を受け取ります。
そこで、tf.estimator.inputs.numpy_input_fnを利用して、辞書を返す関数を作成しています。

tf.estimator.inputs.numpy_input_fn(https://www.tensorflow.org/api_docs/python/tf/estimator/inputs/numpy_input_fn)は下記のように定義されています。

tf.estimator.inputs.numpy_input_fn(
x,
y=None,
batch_size=128,
num_epochs=1,
shuffle=None,
queue_capacity=1000,
num_threads=1
)

return : Function, that has signature of ()->(dict of features, targets)

どのような値が返っているかのイメージがつかない場合、
公式サイト(https://www.tensorflow.org/api_docs/python/tf/estimator/inputs/numpy_input_fn)
のサンプルにprintを追加したものを実行してみるのも良いかもしれません。

次回に続きます。