機械学習はよりアクセスしやすくなり、「既製のコンポーネント」を使用してこのテクノロジーを適用する機会が増えています。 たとえば、Transfer Learningでは、1つの問題を解決する際に得た経験を使用して、別の同様の問題を解決できます。 ニューラルネットワークは、最初に大量のデータでトレーニングされ、次にターゲットセットでトレーニングされます。

この記事では、食物のある画像の認識の例を使用して、転移学習法の使用方法を説明します。
Machine Learning and Neural Networks for Developersワークショップで
、他の機械学習ツールについて説明します。
画像認識のタスクに直面している場合は、既製のサービスを使用できます。 ただし、独自のデータセットでモデルをトレーニングする必要がある場合は、自分で行う必要があります。
画像分類などの一般的なタスクでは、既成のアーキテクチャ(AlexNet、VGG、Inception、ResNetなど)を使用して、データのニューラルネットワークをトレーニングできます。 さまざまなフレームワークを使用したこのようなネットワークの実装はすでに存在するため、この段階では、その動作原理を深く掘り下げることなく、そのうちの1つをブラックボックスとして使用できます。
ただし、ディープニューラルネットワークは、学習の収束のために大量のデータを要求しています。 また、特定のタスクでは、ニューラルネットワークのすべての層を適切にトレーニングするための十分なデータがないことがよくあります。 Transfer Learningはこの問題を解決します。
画像分類のための転移学習
分類に使用されるニューラルネットワークは、通常、最後の層に
N
出力ニューロンを含みます(
N
はクラスの数)。 このような出力ベクトルは、クラスに属する確率のセットとして扱われます。 食品の画像認識タスクでは、クラスの数は元のデータセットのものと異なる場合があります。 この場合、必要な数の出力ニューロンを使用して、この最後のレイヤーを完全に捨てて新しいレイヤーを配置する必要があります

多くの場合、分類ネットワークの最後に、完全に接続されたレイヤーが使用されます。 このレイヤーを置き換えたため、事前にトレーニングされたウェイトを使用しても機能しません。 ランダムな値で重みを初期化し、ゼロから訓練する必要があります。 事前にトレーニングされたスナップショットから、他のすべてのレイヤーの重みをロードします。
モデルをさらにトレーニングするためのさまざまな戦略があります。 以下を使用します。ネットワーク全体をエンドツーエンド(
エンドツーエンド )でトレーニングします。事前にトレーニングしたウェイトを修正して、少し調整してデータを調整できるようにします。 このプロセスは
微調整と呼ばれ
ます 。
構造部品
問題を解決するには、次のコンポーネントが必要です。
- ニューラルネットワークモデルの説明
- 学習パイプライン
- 干渉パイプライン
- このモデルの事前学習済みの重み
- トレーニングおよび検証データ

この例では、コンポーネント(1)、(2)、および(3)を
、最も軽量なコードを含む
独自のリポジトリから取得します。必要に応じて簡単に把握できます。 この例は、一般的な
TensorFlowフレームワークに実装されます。 選択したフレームワークに適した事前学習済みの重み(4)は、それらが古典的なアーキテクチャの1つに対応する場合に見つけることができます。 デモンストレーション用のデータセット(5)として
Food-101を使用します。
モデル
モデルとして、古典的な
VGGニューラルネットワーク(より正確には
VGG19 )を使用します。 いくつかの欠点にもかかわらず、このモデルはかなり高い品質を示しています。 また、分析も簡単です。 TensorFlow Slimでは、モデルの説明は非常にコンパクトに見えます。
import tensorflow as tf import tensorflow.contrib.slim as slim def vgg_19(inputs, num_classes, is_training, scope='vgg_19', weight_decay=0.0005): with slim.arg_scope([slim.conv2d], activation_fn=tf.nn.relu, weights_regularizer=slim.l2_regularizer(weight_decay), biases_initializer=tf.zeros_initializer(), padding='SAME'): with tf.variable_scope(scope, 'vgg_19', [inputs]): net = slim.repeat(inputs, 2, slim.conv2d, 64, [3, 3], scope='conv1') net = slim.max_pool2d(net, [2, 2], scope='pool1') net = slim.repeat(net, 2, slim.conv2d, 128, [3, 3], scope='conv2') net = slim.max_pool2d(net, [2, 2], scope='pool2') net = slim.repeat(net, 4, slim.conv2d, 256, [3, 3], scope='conv3') net = slim.max_pool2d(net, [2, 2], scope='pool3') net = slim.repeat(net, 4, slim.conv2d, 512, [3, 3], scope='conv4') net = slim.max_pool2d(net, [2, 2], scope='pool4') net = slim.repeat(net, 4, slim.conv2d, 512, [3, 3], scope='conv5') net = slim.max_pool2d(net, [2, 2], scope='pool5')
ImageNetでトレーニングされ、TensorFlowと互換性のあるVGG19の重みは、
事前トレーニングモデルセクションのGitHubのリポジトリからダウンロードされます。
mkdir data && cd data wget http://download.tensorflow.org/models/vgg_19_2016_08_28.tar.gz tar -xzf vgg_19_2016_08_28.tar.gz
データセット
トレーニングおよび検証のサンプルとして、101のカテゴリに分割された10万を超える食品の画像を含む公共の食品データセット
Food-101を使用します。

データセットをダウンロードして解凍します。
cd data wget http://data.vision.ee.ethz.ch/cvl/food-101.tar.gz tar -xzf food-101.tar.gz
トレーニングのデータパイプラインは、データセットから次を解析する必要があるように設計されています。
- クラスのリスト(カテゴリ)
- チュートリアル:写真へのパスのリストと正解のリスト
- 検証セット:写真へのパスのリストと正解のリスト
データセットの場合、
トレーニングセットと
検証セットは個別に分割する必要があります。 Food-101にはすでにそのようなパーティションがあり、この情報は
meta
ディレクトリに保存されます。
DATASET_ROOT = 'data/food-101/' train_data, val_data, classes = data.food101(DATASET_ROOT) num_classes = len(classes)
データ処理を担当するすべての補助機能は、別の
data.py
ファイルに移動されます。
data.py from os.path import join as opj import tensorflow as tf def parse_ds_subset(img_root, list_fpath, classes): ''' Parse a meta file with image paths and labels -> img_root: path to the root of image folders -> list_fpath: path to the file with the list (eg train.txt) -> classes: list of class names <- (list_of_img_paths, integer_labels) ''' fpaths = [] labels = [] with open(list_fpath, 'r') as f: for line in f: class_name, image_id = line.strip().split('/') fpaths.append(opj(img_root, class_name, image_id+'.jpg')) labels.append(classes.index(class_name)) return fpaths, labels def food101(dataset_root): ''' Get lists of train and validation examples for Food-101 dataset -> dataset_root: root of the Food-101 dataset <- ((train_fpaths, train_labels), (val_fpaths, val_labels), classes) ''' img_root = opj(dataset_root, 'images') train_list_fpath = opj(dataset_root, 'meta', 'train.txt') test_list_fpath = opj(dataset_root, 'meta', 'test.txt') classes_list_fpath = opj(dataset_root, 'meta', 'classes.txt') with open(classes_list_fpath, 'r') as f: classes = [line.strip() for line in f] train_data = parse_ds_subset(img_root, train_list_fpath, classes) val_data = parse_ds_subset(img_root, test_list_fpath, classes) return train_data, val_data, classes def imread_and_crop(fpath, inp_size, margin=0, random_crop=False): ''' Construct TF graph for image preparation: Read the file, crop and resize -> fpath: path to the JPEG image file (TF node) -> inp_size: size of the network input (eg 224) -> margin: cropping margin -> random_crop: perform random crop or central crop <- prepared image (TF node) ''' data = tf.read_file(fpath) img = tf.image.decode_jpeg(data, channels=3) img = tf.image.convert_image_dtype(img, dtype=tf.float32) shape = tf.shape(img) crop_size = tf.minimum(shape[0], shape[1]) - 2 * margin if random_crop: img = tf.random_crop(img, (crop_size, crop_size, 3)) else:
モデルトレーニング
モデルトレーニングコードは、次の手順で構成されます。
- トレイン/検証データパイプラインの構築
- 列車/検証グラフの作成(ネットワーク)
- トレイングラフ上の損失の分類関数( クロスエントロピー損失 )の付加
- トレーニング中に検証サンプルの予測の精度を計算するために必要なコード
- スナップショットから事前にトレーニングされたスケールをロードするためのロジック
- トレーニングのためのさまざまな構造の作成
- 学習サイクル自体(反復最適化)
グラフの最後の層は、必要な数のニューロンで構成され、事前に訓練されたスナップショットからロードされるパラメーターのリストから除外されます。
モデルトレーニングコード import numpy as np import tensorflow as tf import tensorflow.contrib.slim as slim tf.logging.set_verbosity(tf.logging.INFO) import model import data
トレーニングを開始した後、TensorFlowにバンドルされており、さまざまなメトリックやその他のパラメーターを視覚化するTensorBoardユーティリティを使用して、進捗を確認できます。
tensorboard --logdir checkpoints/
TensorBoardでのトレーニングの最後に、ほぼ完全な画像が表示されます。
トレイン損失の減少と
検証精度の増加です。

その結果、
checkpoints/vgg19_food
保存されたスナップショットを取得し
checkpoints/vgg19_food
。これはモデルのテスト中に使用します(
推論 )。
モデルテスト
次に、モデルをテストします。 これを行うには:
- 推論専用に設計された新しいグラフを作成します(
is_training=False
) - スナップショットからトレーニング済みの重みをロードする
- 入力テストイメージをダウンロードして前処理します。
- ニューラルネットワークを介して画像を駆動し、予測を取得しましょう
inference.py import sys import numpy as np import imageio from skimage.transform import resize import tensorflow as tf import model

必要なすべてのバージョンのライブラリを備えたDockerコンテナを構築および実行するためのリソースを含むすべてのコードは
このリポジトリにあります。記事を読んだ時点で、リポジトリ内のコードは更新されている可能性があります。
ワークショップ
「開発者向けの機械学習とニューラルネットワーク」では、
機械学習の他のタスクを分析し、学生は集中セッションの終わりまでにプロジェクトを発表します。