次の方法で共有



January 2019

Volume 34 Number 1

[Machine Learning]

Windows の PyTorch について

James McCaffrey

生コードからニューラル ネットワークを作成することは非常に困難ですが、不可能ではありません。幸い、プロセスの高速化に使用できるオープン ソース コード ライブラリが多数あります。これらのライブラリには、CNTK (Microsoft)、TensorFlow (Google)、scikit-learn などがあります。ほとんどのニューラル ネットワーク ライブラリは、パフォーマンスを得るため C++ で記述されていますが、利便性のために Python API を使用しています。

この記事では、人気のある PyTorch ライブラリを使用する方法を説明します。PyTorch は、他の多くのニューラル ネットワーク ライブラリと比較して低い抽象化レベルで動作します。これにより、コードをより細かく制御でき、容易にカスタマイズできますが、追加のコードを作成する必要があります。

このコラムの趣旨を理解するには、図 1 のデモ プログラムを見るのが一番です。このデモ プログラムは、よく知られている Iris データセットをメモリに読み込みます。これは、アヤメ (Iris) の種 (setosa、versicolor、virginica) を 4 つの予測値 (萼片の長さ、萼片の幅、花弁の長さ、花弁の幅) から予測することを目標としています。萼片は、葉のような構造をしています。

PyTorch を使用した Iris データセットの例
図 1 PyTorch を使用した Iris データセットの例

完全な Iris データセットには 150 個のアイテムがあります。このデモ プログラムは、トレーニングに 120 個と、テストに 30 個のアイテムを使用します。このデモでは最初に PyTorch を使用してニューラル ネットワークを作成し、次に 600 回のイテレーションを使用してネットワークをトレーニングします。トレーニングの完了後に、テスト データを使用してモデルが評価されます。トレーニング済みモデルの精度は 90.00% です。つまり、30 個のテスト アイテムのうち 27 個の種を正確に予測できます。

デモでは最後に、これまでに観察されていない新しいアヤメの花の種を予測します。この種の萼片と花弁の値は (6.1, 3.1, 5.1, 1.1) です。予測確率は (0.0454, 0.6798, 0.2748) であり、これは versicolor の予測にマップされます。

今回は、中級レベル以上の C 言語ファミリのプログラミング スキルがあることを前提としますが、PyTorch の知識は問いません。この記事には完全なデモ コードが記載されています。ソース コードと、デモで使用される 2 つのデータ ファイルは、本稿付属のダウンロードから入手することもできます。中心となる考え方を可能な限り明瞭にするために、通常のエラー チェックはすべて削除しています。

PyTorch のインストール

PyTorch をインストールするには、2 つのステップを行います。まず、Python と、いくつかの必要な補助パッケージ (NumPy や SciPy など) をインストールし、PyTorch をアドオン パッケージとしてインストールします。Python と、PyTorch を実行するために必要なパッケージを個別にインストールできますが、Python ディストリビューションをインストールする方法が便利です。Python の Anaconda ディストリビューションには PyTorch を実行するために必要なすべてのパッケージと、その他の有用なパッケージが含まれているため、Anaconda ディストリビューションを使用することを強くお勧めします。この記事では、Windows 10 コンピューターへのインストールについて説明します。macOS および Linux システムでのインストールも同じように行えます。

Python、必要な補助パッケージ、および PyTorch のそれぞれの互換性のあるバージョンを調整することは簡単ではありません。これまでに見聞きしてきたほとんどのインストールの失敗は、バージョンの互換性がないことに起因しています。この記事の執筆時点では、Ananconda3 5.2.0 (Python 3.6.5、NumPy 1.14.3、SciPy 1.1.0 を含む) と PyTorch 0.4.1 を使用しました。これらはすべて非常に安定していますが、PyTorch は比較的新しく、継続的に開発が行われているため、この記事が公開される時点には新しいバージョンが使用可能になっている可能性があります。

開始する前に、Windows の [コントロール パネル] | [プログラムと機能] を使用して、コンピューターにインストールされているすべての既存の Python システムをアンインストールすることをお勧めします。また、インストール ファイルとプロジェクト (コードとデータ) ファイルを保持するために C:\PyTorch ディレクトリを作成することもお勧めします。

Anaconda ディストリビューションをインストールするには、repo.continuum.io/archive に移動し、Anaconda3 5.2.0-Windows x86_64.exe ファイル (自己解凍型実行可能ファイル) を探します。リンクをクリックすると、実行または保存のためのボタンがあるダイアログが表示されます。[Run (実行)] をクリックします。

Anaconda インストーラーはとても使いやすいインストーラーです。8 つのインストール ウィザード画面が表示されます。各画面ですべての既定値を受け入れ、[Next (次へ)] をクリックします。ただし、1 つだけ例外があります。Python をシステム PATH 環境変数に追加するかどうかを尋ねる画面が表示される場合、既定ではこれはオフ (いいえ) になっています。このオプションをオンにすることをお勧めします。このようにすると、システム PATH を手動で編集する必要がありません。既定の設定では、Python インタープリターと 500 を超える互換性のあるパッケージが C:\Users\<user>\AppData\Local\ Continuum\Anaconda3 ディレクトリに配置されます。

PyTorch ライブラリをインストールするには pytorch.org に移動し、[Previous versions of PyTorch (以前のバージョンの PyTorch)] リンクをクリックします。torch-0.4.1-cp36-cp36m-win_amd64.whl という名前のファイルを探します。これは Python の "wheel" ファイルです。.whl ファイルは、Windows の .msi ファイルのようなものと考えることができます。リンクをクリックすると、開くかまたは保存するためのオプションが表示されます。[Save As (名前を付けて保存)] を選択し、.whl ファイルを C:\PyTorch ディレクトリに保存します。PyTorch .whl ファイルが見つからない場合には、bit.ly/2SUiAuj を試してみてください。これは、この記事の執筆時点でこのファイルが存在しているページです。

Anaconda ディストリビューションに含まれている Python pip ユーティリティを使用して PyTorch をインストールできます。Windows コマンド シェルを開き、PyTorch .whl ファイルを保存したディレクトリに移動します。次のコマンドを入力します。

C:\PyTorch> pip install torch-0.4.1-cp36-cp36m-win_amd64.whl

インストールは短時間で済みますが、失敗する可能性のあるものが多数あります。インストールが失敗した場合は、シェルに表示されるエラー メッセージを慎重に読んでください。ほとんどの場合、問題はバージョンの互換性に関するものです。

Python と PyTorch のインストールが正常に完了していることを確認するには、コマンド シェルを開き、“python” と入力して Python インタープリターを起動します。“>>>” Python プロンプトが表示されます。次のコマンドを入力します (version コマンドには 2 つの連続するアンダースコア文字があることに注意してください)。

C:\>python
>>> import torch as T
>>> T.__version__
'0.4.1'
>>> exit()
C:\>

上述の応答が表示されたら、PyTorch を使用してニューラル ネットワーク機械学習コードを記述できます。

Iris データセットの準備

Iris 生データセットは bit.ly/1N5br3h にあります。データは次のようになっています。

5.1, 3.5, 1.4, 0.2, Iris-setosa
4.9, 3.0, 1.4, 0.2, Iris-setosa
...
7.0, 3.2, 4.7, 1.4, Iris-versicolor
6.4, 3.2, 4.5, 1.5, Iris-versicolor
...
6.2, 3.4, 5.4, 2.3, Iris-virginica
5.9, 3.0, 5.1, 1.8, Iris-virginica

各行の最初の 4 つの値は、花の萼片の長さ、萼片の幅、花弁の長さ、花弁の幅です。5 番目の項目は、予測する種です。生データには 50 個の setosa、50 個の versicolor、50 個の virginica がこの順序で含まれています。トレーニング ファイルはそれぞれの種の最初の 40 項目 (120 項目) であり、テスト ファイルはそれぞれの種の最後の 10 項目 (30 項目) です。予測変数は 4 個あるため、データセットのグラフを作成するのは現実的ではありません。しかし、図 2 に示すグラフを調べることで、データの構造を大まかに把握できます。

Iris データの一部
図 2 Iris データの一部

ニューラル ネットワークは数値のみを解釈するため、種をエンコードする必要があります。ほとんどのニューラル ネットワーク ライブラリでは、setosa を (1, 0, 0) に、versicolor を (0, 1, 0) に、virginica を (0, 0, 1) にそれぞれ置き換えます。これは 1-of-N エンコードまたは one-hot エンコードと呼ばれます。ただし PyTorch は、バック グラウンドで one-hot エンコードを実行し、3 つのクラスに対し 0、1、または 2 が予期されます。したがって、PyTorch のエンコード済みデータは次のようになります。

5.1, 3.5, 1.4, 0.2, 0
4.9, 3.0, 1.4, 0.2, 0
...
7.0, 3.2, 4.7, 1.4, 1
6.4, 3.2, 4.5, 1.5, 1
...
6.2, 3.4, 5.4, 2.3, 2
5.9, 3.0, 5.1, 1.8, 2

ほとんどの状況では、予測変数を正規化する必要があります。これは通常、スケーリングにより行われます。このため、min-max 正規化と呼ばれる手法を使用して、すべての値が 0.0 から 1.0 の間の値になります。今回はデモをシンプルにするため、Iris データを正規化しませんでした。ニューラル ネットワークを扱うときには通常、問題のためのルート フォルダー (C:\PyTorch\Iris など) を作成し、データ ファイルを保存する Data という名前のサブディレクトリを作成します。

デモ プログラム

スペースを節約するために少し編集した完全なデモ プログラムを図 3 に示します。一般的にはスペース 4 文字でインデントしますが、領域を節約するために、デモでは 2 文字にしています。デモ プログラムの編集にはメモ帳を使用しましたが、高度な機能を搭載した Python エディターが多数あります。Python では行継続文字として ‘\’ が使用されます。 

図 3 Iris データセット デモ プログラム

# iris_nn.py
# PyTorch 0.4.1 Anaconda3 5.2.0 (Python 3.6.5)
import numpy as np
import torch as T
# -----------------------------------------------------------
class Batch:
  def __init__(self, num_items, bat_size, seed=0):
    self.num_items = num_items; self.bat_size = bat_size
    self.rnd = np.random.RandomState(seed)
  def next_batch(self):
    return self.rnd.choice(self.num_items, self.bat_size,
      replace=False)
# -----------------------------------------------------------
class Net(T.nn.Module):
  def __init__(self):
    super(Net, self).__init__()
    self.fc1 = T.nn.Linear(4, 7)
    T.nn.init.xavier_uniform_(self.fc1.weight)  # glorot
    T.nn.init.zeros_(self.fc1.bias)
    self.fc2 = T.nn.Linear(7, 3)
    T.nn.init.xavier_uniform_(self.fc2.weight)
    T.nn.init.zeros_(self.fc2.bias)
  def forward(self, x):
    z = T.tanh(self.fc1(x))
    z = self.fc2(z)  # see CrossEntropyLoss() below
    return z
# -----------------------------------------------------------
def accuracy(model, data_x, data_y):
  X = T.Tensor(data_x)
  Y = T.LongTensor(data_y)
  oupt = model(X)
  (_, arg_maxs) = T.max(oupt.data, dim=1)
  num_correct = T.sum(Y==arg_maxs)
  acc = (num_correct * 100.0 / len(data_y))
  return acc.item()
# -----------------------------------------------------------
def main():
  # 0. get started
  print("\nBegin Iris Dataset with PyTorch demo \n")
  T.manual_seed(1);  np.random.seed(1)
  # 1. load data
  print("Loading Iris data into memory \n")
  train_file = ".\\Data\\iris_train.txt"
  test_file = ".\\Data\\iris_test.txt"
  train_x = np.loadtxt(train_file, usecols=range(0,4),
    delimiter=",",  skiprows=0, dtype=np.float32)
  train_y = np.loadtxt(train_file, usecols=[4],
    delimiter=",", skiprows=0, dtype=np.float32)
  test_x = np.loadtxt(test_file, usecols=range(0,4),
    delimiter=",",  skiprows=0, dtype=np.float32)
  test_y = np.loadtxt(test_file, usecols=[4],
    delimiter=",", skiprows=0, dtype=np.float32)
  # 2. define model
  net = Net()
# -----------------------------------------------------------
  # 3. train model
  net = net.train()  # set training mode
  lrn_rate = 0.01; b_size = 12
  max_i = 600; n_items = len(train_x)
  loss_func = T.nn.CrossEntropyLoss()  # applies softmax()
  optimizer = T.optim.SGD(net.parameters(), lr=lrn_rate)
  batcher = Batch(num_items=n_items, bat_size=b_size)
  print("Starting training")
  for i in range(0, max_i):
    if i > 0 and i % (max_i/10) == 0:
      print("iteration = %4d" % i, end="")
      print("  loss = %7.4f" % loss_obj.item(), end="")
      acc = accuracy(net, train_x, train_y)
      print("  accuracy = %0.2f%%" % acc)
    curr_bat = batcher.next_batch()
    X = T.Tensor(train_x[curr_bat])
    Y = T.LongTensor(train_y[curr_bat])
    optimizer.zero_grad()
    oupt = net(X)
    loss_obj = loss_func(oupt, Y)
    loss_obj.backward()
    optimizer.step()
  print("Training complete \n")
  # 4. evaluate model
  net = net.eval()  # set eval mode
  acc = accuracy(net, test_x, test_y)
  print("Accuracy on test data = %0.2f%%" % acc) 
  # 5. save model
  # TODO
# -----------------------------------------------------------
  # 6. make a prediction
  unk = np.array([[6.1, 3.1, 5.1, 1.1]], dtype=np.float32)
  unk = T.tensor(unk)  # to Tensor
  logits = net(unk)  # values do not sum to 1.0
  probs_t = T.softmax(logits, dim=1)  # as Tensor
  probs = probs_t.detach().numpy()    # to numpy array
  print("\nSetting inputs to:")
  for x in unk[0]: print("%0.1f " % x, end="")
  print("\nPredicted: (setosa, versicolor, virginica)")
  for p in probs[0]: print("%0.4f " % p, end="")
  print("\n\nEnd Iris demo")
if __name__ == "__main__":
  main()

PyTorch プログラムの構造は、その他のライブラリの構造と多少異なります。このデモでは、プログラム定義クラス Batch が、指定された数までのトレーニング用のトレーニング アイテムを処理します。クラス Net は 4-7-3 ニューラル ネットワークを定義します。関数 accuracy は、指定されたモデル/ネットワークを使用してデータの分類の精度 (正しい予測の割合) を計算します。制御ロジックはすべて main 関数に含まれています。

PyTorch と Python は開発速度が速いため、使用中のバージョンを示すコメントを含める必要があります。Python を初めて利用するプログラマの多くは、ベース Python で配列がサポートされていないことに驚きます。PyTorch では NumPy 配列が使用されるため、ほぼ常に NumPy パッケージをインポートします。

ニューラル ネットワークの定義

ニューラル ネットワークの定義は次のように始まります。

class Net(T.nn.Module):
  def __init__(self):
    super(Net, self).__init__()
    self.fc1 = T.nn.Linear(4, 7)
    T.nn.init.xavier_uniform_(self.fc1.weight)
    T.nn.init.zeros_(self.fc1.bias)
...

最初のコード行は、クラスが T.nn.Module クラスを継承することを示しています。T.nn.Module クラスには、ニューラル ネットワークを作成するための関数が含まれています。__init__ 関数はクラス コンストラクターとみなすことができます。オブジェクト fc1 (「常時接続層 1」) はネットワークの非表示の層であり、4 つの入力値 (予測値) を必要とし、7 個の処理ノードを持っています。隠れノードの数はハイパーパラメーターであり、試行錯誤した上で決定する必要があります。非表示の層の重みは、Xavier の一様分布アルゴリズム (他のほとんどのライブラリでは Glorot の一様分布と呼ばれます) を使用して初期化されます。非表示の層のバイアスはすべてゼロに初期化されます。

ネットワーク出力層は、次のように定義されます。

self.fc2 = T.nn.Linear(7, 3)
T.nn.init.xavier_uniform_(self.fc2.weight)
T.nn.init.zeros_(self.fc2.bias)

出力層は、非表示の層からの 7 つの入力を必要とし、種ごとに 1 つずつ、3 つの出力値を生成します。非表示の層と出力層は、この時点では論理的に接続されていないことに注意してください。この接続は必須の foward 関数によって確立されます。

def forward(self, x):
  z = T.tanh(self.fc1(x))
  z = self.fc2(z)  # no softmax!
  return z

この関数は、入力予測値である x を受け入れます。これらの値は非表示の層に渡され、その結果が tanh 活性化関数に渡されます。その結果は出力層に渡され、最終的な結果が返されます。多くのニューラル ネットワーク ライブラリとは異なり、PyTorch では softmax 活性化を出力層に適用しません。これは、softmax はトレーニング損失関数により自動的に適用されるためです。出力層に softmax を適用した場合、ネットワークは機能しますが、softmax を 2 回適用することになるためトレーニングに時間がかかる可能性があります。

メモリへのデータの読み込み

PyTorch を使用するときには、NumPy 配列でデータをメモリに読み込み、この配列を PyTorch Tensor オブジェクトに変換します。Tensor は、GPU プロセッサにより処理できる高度な配列と考えることができます。

NumPy 配列にデータを読み込むにはいくつかの方法があります。筆者の同僚の間で最も一般的な手法は、Python Pandas (元々「パネル データ」と呼ばれていましたが、現在では「Python データ分析」と呼ばれています) パッケージを使用する方法です。ただし、Pandas は習得に多少時間がかかるため、デモ プログラムではシンプルにするために NumPy loadtxt 関数を使用します。トレーニング データが次のように読み込まれます。

train_file = ".\\Data\\iris_train.txt"
train_x = np.loadtxt(train_file, usecols=range(0,4),
  delimiter=",",  skiprows=0, dtype=np.float32)
train_y = np.loadtxt(train_file, usecols=[4],
  delimiter=",", skiprows=0, dtype=np.float32)

PyTorch は、予測値が配列の配列 (array-of-arrays) 形式のマトリックスに含まれており、予測するクラス値が配列に含まれていることを必要とします。これらのステートメントの実行後に、マトリックス train_x will には 120 行と 4 列が含まれ、train_y は 120 個の値が含まれている配列になります。ほとんどのニューラル ネットワーク ライブラリ (PyTorch を含む) では、既定のデータ型として float32 が使用されます。これは、64 ビット変数を使用する場合に、発生するパフォーマンスのペナルティに比べ、得られる精度にはそれほど価値がないためです。

ニューラル ネットワークのトレーニング

このデモはニューラル ネットワークを作成し、次のステートメントを使用してトレーニングの準備を行います。

net = Net()
net = net.train()  # set training mode
lrn_rate = 0.01; b_size = 12
max_i = 600; n_items = len(train_x)
loss_func = T.nn.CrossEntropyLoss()  # applies softmax()
optimizer = T.optim.SGD(net.parameters(), lr=lrn_rate)
batcher = Batch(num_items=n_items, bat_size=b_size)

このデモでは、ネットワークをトレーニング モードに設定する必要はありません。これは、トレーニングでは、トレーニングと評価に異なる実行フローを使用するドロップアウトまたはバッチ正規化が使用されないためです。学習率 (0.01)、バッチ サイズ (12)、最大トレーニング イテレーション (600) は、ハイパーパラメーターです。このデモでは、エポックではなくイテレーションが使用されます。これは、1 回のエポックでは通常、すべてのトレーニング アイテムが 1 つずつ処理されるためです。1 回のイテレーションでは、12 個のトレーニング アイテムが処理されます。

3 つ以上のクラスを予測する多クラス分類の問題に関するエラーを測定するため、CrossEntropyLoss 関数が使用されます。よくあるエラーとして、二項分類に使用することがあります。このデモでは確率的勾配降下法 (最も基本的なトレーニング最適化形式) を使用します。現実的な問題に対応するため、PyTorch では高度なアルゴリズム (Adam (adaptive moment estimation)、Adagrad (adaptive gradient)、RMSprop (resilient mean squared propagation) など) をサポートしています。

プログラム定義の Batch クラスは最もシンプルなバッチ処理メカニズムを実装します。その next_batch 関数を呼び出すたびに、120 個のトレーニング データ インデックスからランダムに選択された 12 個のインデックスが返されます。この手法では、すべてのトレーニング アイテムが同じ回数だけ使用されることは保証されません。実際のシナリオでは、すべてのインデックスが 1 回選択されるまでインデックスをランダムに選択し、その後リセットする高度なバッチ処理支援プログラムを実装することがあります。

トレーニングは正確に 600 回実行されます。このデモでは、600/10 = 60 イテレーションごとに進行情報が表示されます。

for i in range(0, max_i):
  if i > 0 and i % (max_i/10) == 0:
    print("iteration = %4d" % i, end="")
    print("  loss = %7.4f" % loss_obj.item(), end="")
    acc = accuracy(net, train_x, train_y)
    print("  accuracy = %0.2f%%" % acc)

12 個のトレーニング アイテムからなる現行バッチの平均交差エントロピー損失/エラー値には、オブジェクトの item 関数を使用してアクセスできます。一般に、交差エントロピー損失はトレーニング中には解釈が困難ですが、これをモニターして、徐々に減少していること (つまりトレーニングが機能していること) を確認します。

この記事の執筆時点では、PyTorch には分類の精度を示す組み込み関数がありません。プログラム定義の accuarcy 関数は、現在の重みとバイアスの値を使用してモデルの分類精度を計算します。精度は、損失やエラーに比べ容易に解釈できますが、これは大まかなメトリックです。

トレーニング ループ内では、120 個のアイテムからなるデータセットからアイテム バッチが選択され、Tensor オブジェクトに変換されます。

curr_bat = batcher.next_batch()
X = T.Tensor(train_x[curr_bat])
Y = T.LongTensor(train_y[curr_bat])

curr_bat はトレーニング データの 12 個のインデックスからなる配列であるため、train_x[curr_bat] には 12 行 4 列が含まれています。このマトリックスは Tensor 関数に渡され、PyTorch Tensor オブジェクトに変換されます。分類の問題の場合、エンコードされたクラス ラベル値を Tensor オブジェクトではなく LongTensor オブジェクトに変換する必要があります。

実際のトレーニングは、次の 5 つのステートメントにより実行されます。

optimizer.zero_grad()
oupt = net(X)
loss_obj = loss_func(oupt, Y)
loss_obj.backward()
optimizer.step()

これらのステートメントは、誤差逆伝播法を使用してトレーニングを実行する PyTorch の魔法の呪文と考えることができます。最初に、前回のイテレーションの重みとバイアスの勾配値をゼロに設定する必要があります。net 関数の呼び出しでは、12 個の Tensor オブジェクトからなる現行バッチがネットワークに渡され、forward 関数を使用して 12 個の出力値が計算されます。backword と step の呼び出しでは、勾配値が計算され、計算された勾配値を使用して重みとバイアスが更新されます。

モデルの評価と使用

このデモではトレーニングの完了後に、テスト データに対するモデルの精度が計算されます。

net = net.eval()  # set eval mode
acc = accuracy(net, test_x, test_y)
print("Accuracy on test data = %0.2f%%" % acc)

以前と同様に、この例ではモデルを評価モードに設定する必要はありませんが、明示的にしても特にデメリットはありません。デモ プログラムはトレーニング済みモデルを保存しませんが、実際の状況ではトレーニング済みモデルを保存することがあります。PyTorch とその他のほとんどのニューラル ネットワーク ライブラリ (TensorFlow を除く) では、Open Neural Network Exchange (ONNX) フォーマットがサポートされています。

このデモでは、トレーニング済みモデルを使用して前例のない新種のアヤメの種を予測します。

unk = np.array([[6.1, 3.1, 5.1, 1.1]], dtype=np.float32)
unk = T.tensor(unk)  # to Tensor
logits = net(unk)  # values do not sum to 1.0
probs_t = T.softmax(logits, dim=1)  # as Tensor
probs = probs_t.detach().numpy()    # to numpy array

net 関数の呼び出しから返される 3 つの値の合計が必ずしも 1.0 にならないことがあります (例: (3,2, 4.5, 0.3))。したがって、このデモでは 3 つの値の合計が 1.0 になり、確率として大まかに解釈できるように、出力値を強制するため softmax が適用されます。値は Tensor オブジェクトであるため、NumPy 配列に変換されます。これにより、それらの値を容易に表示できるようになります。

まとめ

この記事では、PyTorch ライブラリについてごく簡単に説明しましたが、PyTorch を試しに使ってみる上で必要なすべての情報がカバーされています。この記事で説明したように、PyTorch は CNTK、TensorFlow、scikit-learn とは大きく異なり、低いレベルで動作します。「どのニューラル ネットワーク ライブラリが最適であるか」という質問をよく聞きます。 時間をかけて主要なライブラリをすべて理解することが理想的です。しかしライブラリは非常に複雑であるため、実際には、私のほとんどの同僚は 1 つの主なライブラリだけを使用しています。個人的には、技術的な観点から最適なライブラリを挙げるとすれば、CNTK、Keras/TensorFlow、そして PyTorch の 3 つになります。ただしこれらのライブラリはすべて優れているため、1 つだけ選ぶ場合には、各自のプログラミング スタイルと、同僚や所属企業で最もよく利用されているライブラリに基づいて選ぶことになります。


Dr.James McCaffreyは、ワシントン州レドモンドの Microsoft Research に勤務しています。これまでに、Internet Explorer、Bing などの複数のマイクロソフト製品にも携わってきました。Dr.McCaffrey の連絡先は jammc@microsoft.com (英語のみ) です。

この記事のレビューに協力してくれたマイクロソフト技術スタッフのBrian Broll、Yihe Dong、Chris Lee に心より感謝いたします。