[51CTO.com からのオリジナル記事] ディープラーニングを軸に早くから事業を開始した中国の AI ユニコーン企業 Megvii は、自社開発のディープラーニング フレームワーク MegEngine (Brain++ のコア コンポーネントの 1 つ) のオープンソース リリースを発表しました。中国語名は「天元」で、囲碁盤の中心点に由来しています。 [[320459]] 今日は、Tianyuan ディープラーニング フレームワークを体験する方法を紹介します。Tianyuan ディープラーニング エンジンをインストールするには、Linux が必要です。現在、Tianyuan は Linux のみをサポートしており、Windows に慣れている人にとっては使いにくいです。 Windows サブ Linux にインストールする必要があります。デュアル システムと Linux ベアメタルをインストールしない限り、GPU ディープラーニング アクセラレーションはサポートされない可能性があります。これはあまり便利ではありません。しかし、国産のスタートアップエンジンは理解可能であり、今後確実に改善されるでしょう。 pip3 をインストール megengine -f https://megengine.org.cn/whl/mge.html これにより、直接インストールが可能になります。 手書き認識データセットの公式ウェブサイトはこちらです。主に手書き認識用のデータセットシリーズが含まれています。 http://yann.lecun.com/exdb/mnist/index.html からデータセットをダウンロードできます。 MNIST データセット内の画像は 28*28 です。各画像は長さ 28*28=784 の行ベクトルに変換され、各値はピクセルを表します。データセットには 55,000 のトレーニング データと 5,000 のテスト データを含む 60,000 の手書きデータ画像が含まれています。 MNISTでは、mnist.train.imagesは形状[55000, 784]のテンソルであり、最初の次元は画像のインデックスに使用され、2番目の次元は画像内のピクセルです。 MNIST データセットは、トレーニング データセット、検証データセット、テスト データセット (mnist.validation) の 3 つの部分で構成されます。 ラベルは0から9までの数字で、画像内の数字を表すために使用されます。ワンホットベクトルに変換すると、表される数字に対応する添え字が1になり、残りの値は0になります。ラベル付きトレーニングデータはサイズ[55000, 10]の数値行列です。 今日はMNISTを受験してみましょう。 手書き認識のためのディープラーニングを実行しているTianyuanです。今日は、GPU シナリオでディープラーニングのトレーニング速度をテストしてみましょう。 GPU には NVIDIA グラフィック カード 1080ti を使用します。 3 つの主要フレームワークのトレーニング速度とコード実装の俊敏性を比較します。 以下は天元エンジンコードです。 - from megengine.data.dataset import MNIST #データセットをインポート
- train_dataset = MNIST(root= "./dataset/MNIST"、train= True 、download= True )
- test_dataset = MNIST(root= "./dataset/MNIST"、train= False 、download= False )
- megengine.module を Mとしてインポートします
- megengine.function を Fとしてインポートします。
- クラスNet(M.Module):
- __init__(self)を定義します。
- スーパー().__init__()
- self.conv0 = M.Conv2d(1, 20, kernel_size=5, バイアス= False )
- 自己.bn0 = M.BatchNorm2d(20)
- 自己.relu0 = M.ReLU()
- 自己.pool0 = M.MaxPool2d(2)
- self.conv1 = M.Conv2d(20, 20, kernel_size=5, バイアス= False )
- 自己.bn1 = M.BatchNorm2d(20)
- 自己.relu1 = M.ReLU()
- 自己.プール1 = M.MaxPool2d(2)
- self.fc0 = M.Linear(500, 64, バイアス= True )
- 自己.relu2 = M.ReLU()
- self.fc1 = M.Linear(64, 10, バイアス= True )
- def forward (self, x):
- x = 自己.conv0(x)
- x = 自己.bn0(x)
- x = 自己.relu0(x)
- x = 自己.pool0(x)
- x = 自己.conv1(x)
- x = 自己.bn1(x)
- x = 自己.relu1(x)
- x = 自己.プール1(x)
- x = F.flatten(x, 1)
- x = 自己.fc0(x)
- x = 自己.relu2(x)
- x = 自己.fc1(x)
- xを返す
- megengine.jitからインポートトレース
- @trace(シンボリック = True )
- def train_func(データ、ラベル、*、opt、ネット):
- ネット.トレイン()
- 予測 = ネット(データ)
- 損失 = F.cross_entropy_with_softmax(予測、ラベル)
- opt.backward(損失)
- リターン予測、損失
- @trace(シンボリック = True )
- def eval_func(データ、ラベル、*、ネット):
- ネット評価()
- 予測 = ネット(データ)
- 損失 = F.cross_entropy_with_softmax(予測、ラベル)
- リターン予測、損失
- インポート時間
- numpyをnpとしてインポートする
- megengine を mgeとしてインポートします
- megengine.optimizerからSGD をインポートします
- megengine.dataからDataLoaderをインポートします
- megengine.data.transformからToMode、Pad、Normalize、Compose をインポートします
- megengine.data.samplerからRandomSampler をインポートします
- # トレーニングデータを読み込み、前処理する
- データローダー = データローダー(
- トレーニングデータセット、
- 変換=作成([
- 正規化(平均=0.1307*255、標準偏差=0.3081*255)、
- パッド(2)
- ToMode( 'CHW' )、
- ])、
- サンプラー=RandomSampler(データセット=train_dataset、バッチサイズ=64)、
- # トレーニング中、RandomSamplerは通常、データの順序を乱すために使用されます
- )
- # ネットワークをインスタンス化する
- ネット = ネット()
- # SGD最適化法、学習率 lr=0.01、運動量 momentum=0.9
- オプティマイザー = SGD(net.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
- total_epochs = 10 # 合計10エポックを実行します
- 範囲(total_epochs)内のエポックの場合:
- 合計損失 = 0
- ステップ、(batch_data、batch_label) を enumerate(dataloader)で指定します。
- batch_label = batch_label.astype(np.int32)
- optimizer.zero_grad() # パラメータの勾配をゼロに設定する
- pred、loss = train_func(batch_data、batch_label、opt=optimizer、net=net)
- optimizer.step() # 勾配に応じてパラメータ値を更新
- 合計損失 += loss.numpy().item()
- print( "エポック: {}, 損失 {}" .format(エポック, total_loss/len(データローダー)))
- mge.save(net.state_dict(), 'mnist_net.mge' ) を実行します。
- ネット = ネット()
- state_dict = mge.load ( 'mnist_net.mge' )
- net.load_state_dict(状態ディクショナリ)
- megengine.data.samplerからSequentialSampler をインポートします
- # テストデータ
- test_sampler = SequentialSampler(テストデータセット、バッチサイズ=500)
- データローダーテスト = データローダー(
- テストデータセット、
- サンプラー=テストサンプラー、
- 変換=作成([
- 正規化(平均=0.1307*255、標準偏差=0.3081*255)、
- パッド(2)
- ToMode( 'CHW' )、
- ])、
- )
- 正解 = 0
- 合計 = 0
- enumerate(dataloader_test)内のidx、(batch_data、batch_label)について:
- batch_label = batch_label.astype(np.int32)
- pred、loss = eval_func(batch_data、batch_label、net=net)
- 予測 = F.argmax(予測、軸=1)
- 正解 += (予測 == batch_label) .sum ().numpy().item()
- 合計 += batch_label.shape[0]
- print( "正解: {}, 合計: {}, 精度: {}" .format(正解, 合計, float (正解) / 合計))
これは TensorFlow バージョンです。 - テンソルフローをtfとしてインポートする
- numpyをnpとしてインポートする
- tensorflow.examples.tutorials.mnistからinput_dataをインポートします
- matplotlib.pyplot を pltとしてインポートします。
- mnist = input_data.read_data_sets( 'MNIST_data' 、 one_hot = True )
- tf.reset_default_graph()
- x = tf.placeholder(tf.float32, [なし、784])
- y = tf.placeholder(tf.float32, [なし, 10])
- w = tf.Variable(tf.random_normal([784, 10]))
- b = tf.Variable(tf.zeros([10]))
- 予測 = tf.matmul(x, w) + b
- 予測 = tf.nn.softmax(予測)
- コスト = tf.reduce_mean(-tf.reduce_sum(y * tf.log(pred), reduction_indices=1))
- 学習率 = 0.01
- オプティマイザー = tf.train.GradientDescentOptimizer(learning_rate).minimize(コスト)
- トレーニングエポック = 25
- バッチサイズ = 100
- 表示ステップ = 1
- 保存パス = 'model/'
- セーバー = tf.train.Saver()
- tf.Session() を sessとして使用:
- sess.run(tf.global_variables_initializer())
- 範囲内のエポックの場合(training_epochs):
- 平均コスト = 0
- total_batch = int (mnist.train.num_examples/batch_size)
- i が範囲内(total_batch)の場合:
- batch_xs、batch_ys = mnist.train.next_batch(batch_size)
- _, c = sess.run([オプティマイザ、コスト]、feed_dict={x:batch_xs、y:batch_ys})
- 平均コスト += c / 合計バッチ
- (エポック + 1) % display_step == 0 の場合:
- print( 'epoch=' , epoch+1, 'cost=' , avg_cost) を出力します。
- print( '終了' )
- 正しい予測 = tf.equal(tf.argmax(予測, 1), tf.argmax(y, 1))
- 精度 = tf.reduce_mean( tf.cast (correct_prediction, tf.float32))
- print( '精度: ' , 精度評価({x:mnist.test.images, y:mnist.test.labels}))
- 保存 = saver.save(sess, save_path=save_path+ 'mnist.cpkt' )
- print( " 2 番目のセッションを開始します...... " )
- tf.Session() を sessとして使用:
- sess.run(tf.global_variables_initializer())
- saver.restore(sess, save_path=save_path+ 'mnist.cpkt' ) を復元します。
- 正しい予測 = tf.equal(tf.argmax(予測, 1), tf.argmax(y, 1))
- 精度 = tf.reduce_mean( tf.cast (correct_prediction, tf.float32))
- print( '精度: ' , 精度評価({x: mnist.test.images, y: mnist.test.labels}))
- 出力= tf.argmax(予測, 1)
- batch_xs、batch_ys = mnist.test.next_batch(2)
- outputval = sess.run([出力], feed_dict={x:batch_xs, y:batch_ys})
- print(出力値)
- im = バッチ_xs[0]
- im = im.reshape(-1, 28)
- plt.imshow(im, cmap= 'グレー' )
- plt.show()
- im = バッチ_xs[1]
- im = im.reshape(-1, 28)
- plt.imshow(im, cmap= 'グレー' )
- plt.show()
こちらはPyTorchバージョンです。 - 輸入トーチ
- torch.nnをnnとしてインポートする
- torch.nn.function を Fとしてインポートします。
- torch.optim を optimとしてインポートします
- torchvisionからデータセットをインポートし、変換する
- torch.autogradから変数をインポート
- バッチサイズ = 64
- train_dataset = datasets.MNIST(root= './data/' ,
- 訓練=真、
- 変換 = transforms.ToTensor()、
- ダウンロード = True )
- test_dataset = datasets.MNIST(root= './data/' ,
- 列車 = False 、
- 変換 = transforms.ToTensor())
- # データローダー (入力パイプライン)
- train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
- バッチサイズ=バッチサイズ、
- シャッフル = True )
- test_loader = torch.utils.data.DataLoader(データセット=test_dataset,
- バッチサイズ=バッチサイズ、
- シャッフル = False )
- クラスNet(nn.Module):
- __init__(self)を定義します。
- super(Net, self).__init__()
- # 入力 1 チャネル、出力 10 チャネル、カーネル 5*5
- self.conv1 = nn.Conv2d(in_channels=1、out_channels=10、カーネルサイズ=5)
- 自己.conv2 = nn.Conv2d(10, 20, 5)
- 自己.conv3 = nn.Conv2d(20, 40, 3)
- 自己.mp = nn.MaxPool2d(2)
- # 完全接続
- self.fc = nn.Linear(40, 10) #(in_features、out_features)
- def forward (self, x):
- # インサイズ = 64
- in_size = x.size (0) # 1バッチ このとき、xはバッチサイズの次元が4のテンソルです。
- つまり、(batchsize,channels,x,y)、 x.size (0)はbatchsizeの値を参照します。
- batchsize値をネットワークのin_sizeとして使用します
- # x: 64*1*28*28
- x = F.relu(self.mp(self.conv1(x)))
- # x: 64*10*12*12 特徴マップ =[(28-4)/2]^2=12*12
- x = F.relu(self.mp(self.conv2(x)))
- # x: 64*20*4*4
- x = F.relu(self.mp(self.conv3(x)))
- x = x.view (in_size, -1) # resharpに相当するテンソルを平坦化する
- # 印刷( x.size ())
- # x: 64*320
- x = 自己.fc(x)
- # x:64*10
- # 印刷( x.size ())
- F.log_softmax(x) #64*10を返す
- モデル = ネット()
- オプティマイザー = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
- def train(エポック):
- batch_idx、(データ、ターゲット)をenumerate(train_loader)で指定します。
- #batch_idxはenumerate()関数のインデックスで、0から始まります。
- #データサイズ():[64, 1, 28, 28]
- #ターゲットサイズ():[64]
- 出力= モデル(データ)
- #出力:64*10
- 損失 = F.nll_loss(出力, ターゲット )
- batch_idx % 200 == 0の場合:
- print( 'トレーニングエポック: {} [{}/{} ({:.0f}%)]\t損失: {:.6f}' .format(
- エポック、batch_idx * len(データ)、len(train_loader.dataset)、
- 100. * batch_idx / len(train_loader)、 loss.data[0]))
- optimizer.zero_grad() # すべてのパラメータの勾配をゼロにクリアします
- loss.backward() #勾配を求めるための逆伝播
- optimizer.step() # オプティマイザを呼び出して勾配降下法を実行し、パラメータを更新します
- デフテスト():
- テスト損失 = 0
- 正解 = 0
- データの場合、test_loaderのターゲット:
- データ、ターゲット = 変数(データ、揮発性= True )、変数(ターゲット)
- 出力= モデル(データ)
- # バッチ損失を合計する
- test_loss += F.nll_loss(出力, ターゲット , size_average= False ).data[0]
- #最大対数確率のインデックスを取得します
- pred =出力.data . max (1, keepdim = True )[1]
- 印刷(予測)
- 正しい += pred.eq(target.data.view_as(pred)).cpu(). sum ()
- test_loss /= len(test_loader.dataset)
- print( '\nテストセット: 平均損失: {:.4f}、精度: {}/{} ({:.0f}%)\n' .format(
- test_loss、正しい、len(test_loader.dataset)、
- 100. * 正しい / len(test_loader.dataset)))
- エポックが範囲(1, 10)の場合:
- 列車(時代)
- テスト()
テスト時間、1080ti、Ubuntu 18.04 システムの場合、トレーニング時間は次のとおりです。 メグエンジン 45.3429 テンソルフロー 87.3634 パイトーチ 68.8535 コードを完成させてテストした後、Tianyuan ディープラーニング フレームワーク、TensorFlow、PyTorch について簡単に説明しました。 1. 使いやすさ 使いやすさの点では、MegEngine と PyTorch が最も簡潔で、コードは TensorFlow よりもはるかにシンプルで最適化されており、PyTorch とシームレスに互換性があります。 TensorFlow は比較的複雑で、学習が困難です。すぐに使い始めたい場合には、MegEngine も良い選択肢です。 TensorFlow は比較的扱いにくく、Python などの言語とは大きく異なります。特定の言語をベースにプログラミング言語を再定義したようなもので、デバッグも複雑です。バージョンが更新されるたびに、TensorFlow のさまざまなインターフェースが大幅に変更されることが多く、学習時間が大幅に増加します。 PyTorch は動的な計算グラフをサポートし、カプセル化をできるだけ少なくし、簡潔で読みやすいコードを持ち、アプリケーションの柔軟性が高く、Torch インターフェースを使用し、非常に使いやすく、メイン言語 Python のさまざまな利点をうまく活用できます。 ドキュメントの詳細度という点では、TensorFlow には非常に詳細な公式ドキュメントがあり、見つけやすく、更新速度も速いのですが、構成があまり明確ではなく、チュートリアルが多すぎます。 PyTorch と比較すると、MegEngine はよく整理されています。 PyTorch の方が事例が少し多く、MegEngine はまだ構築中です。今後はもっと増えると思います。全体的に、使いやすさの点では MegEngine は PyTorch とほぼ同じです。 TensorFlow は使いやすさの点では最悪です。 MegEngine は PyTorch からすべてのケースをシームレスに借用できるため、優れた互換性が実現します。 2. スピード MegSpeed は、Tianyuan ディープラーニング フレームワークに多くの最適化を加えました。私のグラフィック カード 1080ti では、MegEngine > PyTorch > TensorFlow です。単一マシンのトレーニング速度に関しては、MegEngine は非常に高速で、メモリの使用量は最小限です。 MegEngine は、究極のメモリ最適化を実現するために静的メモリ割り当てを使用すると言われています。これはかなり珍しいことです。 3. オペレーターの数 この点では、8,000 を超える Python API を提供する TensorFlow が間違いなく最大の勝者です (https://tensorflow.google.cn/api_docs/python を参照)。基本的に、ユーザーが見つけられない演算子はなく、すべてのアルゴリズムは TensorFlow 演算子を使用して説明できます。ただし、低レベルと高レベルの両方で API が多すぎると負担となり、ユーザーを混乱させてしまう可能性があります。 PyTorch の演算子は 2 番目であり、TensorFlow よりも最適化されています。 Tianyuan ディープラーニング フレームワークは現在、演算子の数が最も少ないですが、最適化されており、演算子の品質も高くなっています。その中でも、任意のグラフはMNIST のトレーニングに非常に役立ちます。現在、TensorFlow も PyTorch もサポートされていません。 4. オープンソースモデルデータセットの例 現在は、TensorFlow>PyTorch>MegEngine です。この分野では、TensorFlow が最も長い歴史と最も多くの事例を持ち、次に PyTorch、そして MegEngine が最も少ないです。 5. オープンソースコミュニティ 現在、MegEngine のオープンソース コミュニティは最も小さいですが、準備も整い、確立されつつあります。早めに参加すれば、PyTorch や TensorFlow のようにコミュニティの大物になれるかもしれません。天元ディープラーニングフレームワークにもっと多くの人が採用されれば、より多くの人が学習を促進できるようになるかもしれません。現在、国内での開発はまだ初期段階ですが、私たちは天元のディープラーニングフレームワークの将来について非常に楽観的です。 6. 柔軟性 TensorFlow は主に静的計算グラフをサポートしています。計算グラフの構造は比較的直感的ですが、デバッグ時に非常に複雑で面倒であり、一部のエラーを見つけるのがより困難です。しかし、2017年末に動的グラフ機構Eager Executionがリリースされ、動的計算グラフのサポートが追加されましたが、現在は元の静的計算グラフ形式が依然として主流となっています。 TensorFlow には、実行中のプロセスを監視し、計算グラフを視覚化できる TensorBoard アプリケーションがあります。 PyTorch は動的計算グラフの代表的なものです。デバッグが容易で、高度にモジュール化されているため、モデルの構築に非常に便利です。また、優れた GPU サポートを備えており、データ パラメータを CPU と GPU 間で柔軟に移行できます。 MegEngine は PyTorch とシームレスに互換性があり、動的グラフの利点を備えているため、分散展開とモデル推論に大きな利点をもたらします。 MegEngine の柔軟性は TensorFlow に比べて大きな利点があります。 比較は表形式で表示されます。 注: スコアが高いほど良い まとめると、MegEngine には次のような利点があります。 - 使いやすい
- PyTorch 対応
- 静的グラフメカニズムと動的グラフメカニズムの両方をサポート
- 中国語チュートリアルの詳細
- 中国語コミュニティは英語が苦手な人にとって役に立ちます。
改善が必要な欠点もいくつかあります。 - Windows/Mac およびその他の Linux ディストリビューションをサポートします。現在、Ubuntu 16.04 以降のみがサポートされており、確かに少し制限があります。また、Docker などのインストール方法はサポートされないはずです。
- より多くのケース ライブラリとモデル ライブラリ。
- できるだけ早く主要大学に入学し、教材やチュートリアルを提供し、中国独自の AI 人材プールを構築します。
MegEngineが中国の人工知能産業に独自の貢献を果たし、中国製の人工知能ディープラーニングエンジンを構築し、その輝かしい力を中華民族の台頭に寄与することを期待しています。また、国産のディープラーニングエンジンをうまく活用して、我が国をAI大国に築き上げていくこともできます。 著者について: Yin Cheng は、清華大学で修士号を取得しており、マイクロソフトの人工知能分野で世界で最も価値のある専門家の 1 人です。C/C++、Python、Go、TensorFlow に精通しており、15 年のプログラミング経験と 5 年の教育経験があります。シニア ソフトウェア アーキテクトであり、Intel ソフトウェア テクノロジの専門家でもあります。プロジェクト管理と研究開発の豊富な経験があり、人工知能の発明に関する特許を 2 件保有しています。 51CTO のフォーチュン 500 アルゴリズム コース https://edu..com/sd/0a881 [51CTO オリジナル記事、パートナーサイトに転載する場合は、元の著者とソースを 51CTO.com として明記してください] |