ほとんどのtensorflowチュートリアルでは、著者はチャネルの最後の次元の順序付けを使用します。
input_layer = tf.reshape(features, [-1, 28, 28, 1])
ここで、最後の桁はチャネルの数を表します( https://www.tensorflow.org/tutorials/layers )。 TheanoとNumpyに慣れている(どちらもC順序、つまり行優先を使用する)ので、これは厄介です。さらに、テンソルフローのインメモリレイアウトスキームで documentation を読んだので、チャネルラストレイアウト中に個々のチャネルで畳み込みが実行されるため、チャネルラストレイアウトはより多くのキャッシュミスを引き起こすと考えています。これらのチャネルは線形メモリ内で混合され、キャッシュをN(Nはチャネル数)だけ効果的に縮小します。これは、3Dおよび4D畳み込みでは特に非効率的です。何か問題がありますか?
追伸.
密接に関連するスレッドを見つけました( Tensorflow 3チャンネルの色入力の順序 )。受け入れられた回答の著者は、TFがデフォルトで行優先を使用していると述べていますが、これまでに見つけたすべてのチュートリアルがチャネルの最後の順序を示していることを考えると、誤解を招く主張を見つけます。
説明は次のとおりです。
https://www.tensorflow.org/performance/performance_guide#use_nchw_image_data_format
画像データ形式とは、画像のバッチの表現を指します。 TensorFlowは、NHWC(TensorFlowのデフォルト)およびNCHW(cuDNNのデフォルト)をサポートしています。 Nはバッチ内の画像の数、Hは垂直方向のピクセル数、Wは水平方向のピクセル数、Cはチャネル(例:白黒の場合は1、3の場合は3、 cuDNNは両方の形式で動作できますが、デフォルトの形式で動作する方が高速です。
GPUでNCHWを使用してトレーニングするのが一般的であるため、NCHWとNHWCの両方で動作するモデルを構築し、CPUでNHWCを推論することをお勧めします。
これら2つの形式の非常に短い歴史は、TensorFlowがNHWCを使用して開始したことです。これは、CPUで少し高速だったためです。次に、TensorFlowチームは、NVIDIA cuDNNライブラリを使用するとNCHWのパフォーマンスが向上することを発見しました。現在の推奨事項は、ユーザーがモデルで両方の形式をサポートすることです。長期的には、グラフを書き直して、形式間の切り替えを透過的にする予定です。
さらに、コードを掘り下げると、 here が表示されます。入力がNHWC形式の場合、tensorflowはそれをNCHWに変換します。
if (data_format == FORMAT_NHWC) {
// Convert the input tensor from NHWC to NCHW.
TensorShape nchw_shape =
ShapeFromFormat(FORMAT_NCHW, in_batch, in_rows, in_cols, in_depths);
if (in_depths > 1) {
Tensor transformed_input;
OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
nchw_shape, &transformed_input));
functor::NHWCToNCHW<GPUDevice, T, 4>()(
ctx->eigen_device<GPUDevice>(),
const_cast<const Tensor&>(input).tensor<T, 4>(),
transformed_input.tensor<T, 4>());
input = transformed_input;
} else {
// If depth <= 1, then just reshape.
CHECK(input.CopyFrom(input, nchw_shape));
}
}
すべての操作に使用するデータ形式を指定できますが、デフォルトではテンソルフローはNCHWではなくNHWCを使用します。そのため、TFデベロッパーでもNHWCを使用して、すべての操作で形式の指定を回避します。
あなたの質問は誤解に基づいています。
行優先とNHWCの間に矛盾はありません。行優先とは、右端のインデックスが変更時にメモリ内で最小のジャンプを引き起こし、左端のインデックスの変更が最大のジャンプを引き起こすことを意味します。行優先では、最後の次元が連続し、列優先では、最初の次元が連続します。 https://en.wikipedia.org/wiki/Row-_and_column-major_order#Address_calculation_in_general を参照して、任意の次元数のメモリオフセットを計算する方法を確認してください。
したがって、TFのメモリIS行優先にレイアウトされています。インデックスのorderの違いは微妙です(一部人々はさらにCHWNを好みます- https://github.com/soumith/convnet-benchmarks/issues/66#issuecomment-155944875 を参照してください。 DLは行優先です。