width - みる会図書館


検索対象: TensorFlowはじめました 2
10件見つかりました。

1. TensorFlowはじめました 2

図 27 超解像処理をした画像 ( サイズ調整済み ) . ヾ、 , 1 ツ气ー ご覧の通り、解像度を上げるどころか、低解像度の画像すら再現できていません。 次章では、いったい何が原因でこうなったのか。どのようにして解決するのかを検討します 1 . https://arxiv.org/abs/1501.00092 2. https.//en wikipedia.org/wiki/Feature scaling 3. プロックのサイズは、使用するモデルの定数 INPUT-SIZE で定義しています。今回の場合は 33px になります 4. これは、使用している画像処理ライプラリ P Ⅲ ow の仕様によるものです。 Pillow の f 「 oma 「「 ay 画像を処理する場合、入力データは [height. width] となりますが、 mode= ・ RGB の場合、 [height. width, channel] と、求められる形が異なります 5.510PX と半端なのは、 2 分の 1 、 3 分の 1 と、どちらの場合でも割り切れるため倍率を変えた場合の評価がしやすいと考えたためです 40 第 2 章 CNN で超解像

2. TensorFlowはじめました 2

if biases_shape is not None: —get—biases(biases—shape, value=biases_value) biases conv = tf. nn . bias—add(conv, biases) return conv 畳み込み層は、入力に対して「フィルターによるスキャン」と「バイアスの加算」を行います。 入力とは、 2 次元の画像 + チャンネルの 3 階テンソル [ height , width, channet]lo 厳 密に言えば、、ニバッチのサイズを併せた [batch, height, width, channet] の形をし た 4 階テンソルです。 オペレーション tf. nn . conv2d は、指定した形と枚数 (weights-shape で定義されます ) のフィルターを使って、畳み込み処理をします。 畳み込み処理とは、フィルターをスライドさせて、入力をスキャンすることを言います。 図 3.2 は、フィルターが入力をスキャンする ( 畳み込む ) 様子を図示したものです。 図 3.2 33X33 の入力を、フィルターサイズ 9X9 、スライド幅 1 でスキャンした場合 編第彦第ド 第■・第第を第 第・・第第物当置 を、第を・・をー第 ■日 0 材を ・宿第画ーをー宿 を宿い 置第第重第第宿こ 第第ををき ・をー第 スキャンは左上から開始します。フィルターが右端に到達すると下にスライドして、もう一 度左端からスキャンします。これを繰り返して、次の層への出力マップを作成します。スキャ ン一回分の結果が、出力マップの 1 マスに当たります。 42 ー第 3 章超解像奮闘記

3. TensorFlowはじめました 2

リスト 2.8 : srcnn/eval.py def —pad(image, pad) : if pad [INDEX_PADDING_LEFT] and pad [INDEX_PADDING_TOP] return image w n ew h image . width image . height S 1 w + pad [INDEX_PADDING_LEFT] + pad [INDEX—PADDING_R 工 GHT] , + pad [INDEX_PADDING_TOP] + pad [ 工 NDEX_PADDING_BOTTOM] (pad[INDEX_PADDING_LEFT] , pad[INDEX_PADDING_TOP] ) new—size, color=@xffffff) —image. paste(image, 1 mage lmage . new('RGB' プロックに分割 return new_image 2 次元配列に格納する際、 NumPy の Array 形式に変換します。また、 255 で除算すること サイズとスライド幅は同じ値になります。 stride は、プロックのスライド幅です。プロック同士が重複なく処理する場合、プロック 納します。 リスト 2.9 の関数 __extract_blocks は、画像をプロック 3 に分割したあと 2 次元配列に格 V num image . height / / stride[INDEX—VERTICAL] def extract_blocks(image, stride) : リスト 2.9 : srcnn/eval.py で、ピクセルの値域を @ー 255 から @ . @-I. @ に整えます。 [@ for i in range(h—num)] for j in range(v—num) btocks # blocks [v—num] [h—num] h—num = image . width / / stride[INDEX—HOR 工 ZONTAL] shape (MODEL. INPUT_SIZE, MODEL. INPUT_SIZE, 34 第 2 章 CNN で超解像

4. TensorFlowはじめました 2

それぞれの画像は [height, width, channel] の Tensor です。これらを追加したリスト を、 stack で連結することで [batch_size, height, width, channet] の Tensor を得 ます。 また、機械学習の学習アルゴリズムには、データの値域が広すぎると有効に機能しないもの があります。そのため、最後にそれぞれの値を 255 で除算して、ピクセルの値域 ( 0 ~ 255 ) を @ . @~ 1 . @ に正規化 (Normalize) しています 2 ⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢ 1 枚の画像から切り出すサンプル数 for を使って、一枚の画像から複数の画像を c 「 op ( 切り出し ) をしているのは、 CPU の負荷を下げるのが目的です。 筆者は当初、 f 。「を使わず、 1 枚のサンプル画像から 1 枚の学習用画像を切り出していました。しかし、プログラムを検証 環境で実行した際に、 CPU と I/O が高負荷になって GPU の性能を活かせないという問題が発生しました。 たとえば 128 のミニバッチで学習した場合、大きなサンプル画像から学習用画像を 1 枚しか切り出さないと、一回のバッ チで 128 回のファイルの読み込みとデコードが発生することになります。 そこで、リスト 2.3 のように、 1 枚の画像をデコードしたあと、まとまった数のサンプルを取得することで、 C PU と I/O の 負荷が下がり、 GPU の性能を発揮することができるようになりました。 ⅱⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅱⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅢⅱⅢⅢⅢⅢⅢⅢ 誤差関数の定義 誤差関数 (Loss Function) で、入力をモデルが処理した出力が、期待する出力とどの程度離 れているかを算出します。 関数ーユ。 ss は、画像を扱うときに一般的な MSE (Mean Squared Error: 平均二乗誤差 ) を 最適化アルゴリズムの設定 tf. squared—difference(sr—images, ground—truth)) return tf. reduce_mean( def toss(sr—images, ground—truth) : リスト 2.4srcnn/trai n. py 用いて誤差を求めます ( リスト 2.4 ) 。 関数 __init_optimizer は、 AdamOptimizer を最適化アルゴリズムに設定します ( リス ターを更新します。 最適化アルゴリズムは、誤差関数が算出した誤差をもとに、誤差が小さくなるようにパラメー ず Adam を使用してみて、 ト 2.5 ) 。 どうしても求める精度や性能が出なければ、別の最適化アルゴリズ Adam (Optimizer) は、 2014 年に発表された最適化アルゴリズムです。筆者は学習の際、ま 28 第 2 章 CNN で超解像

5. TensorFlowはじめました 2

print(mul—result) print(add—resuIt2) リスト 1.4 では、加算した結果に const2 を積算するオペレーション mut ー op を実行していま tf. add tf. multiply 図 1 .2 tf. multiply に tf. add と const2 を入力 す。このオペレーションを図にすると図 1.2 のようになります。 constl const2 実行結果は次の通りです。 15 5 このように、セッションの中でグラフを構成するいすれかのオペレーションを実行して結果 を取り出すことができます。 テンソル (Tensor) たとえば画像データを表す場合、 Tensor の Rank は [ 3 ] 、 Shape は [width, height, にはデータ型 (Type) があります ( 表 1.2 ) 。 Rank は「テンソルの階数」、 Shape は「テンソルの形」を意味します ( 表 1.1) 。また、 Tensor Rank と Shape, Type 差し支えありません。 扱います。以後、 Tens 。 rFl 。 w の文脈で触れる「 Tensor 」は、「 n 次元の多次元配列」と考えて TensorFIow は、グラフを構成するすべてのオペレーションを「 Tensor ( テンソル ) 」として channel] 、データ型は tf. uint83 となります。 第 1 章 TensorFIow の基礎 11

6. TensorFlowはじめました 2

図 : プロック単位に処理できるように大きさを調整 リスト 2.7 の関数 __calc_padding は、プロックのスライド幅 (stride) に対して必要な パディングを計算します。 リスト 2.7 : srcnn/eval.py INDEX_PADDING_LEFT = 0 INDEX PADDING TOP INDEX PADDING RIGHT = 2 INDEX PADDING BOTTOM 3 INDEX VERTICAL INDEX HORIZONTAL 1 def __calc—padding(image, stride) : padding—vertical stride[INDEX_VERTICAL] \ image. height % stride[INDEX_VERT 工 CAL] stride[INDEX_HORIZONTAL] \ image. width % stride[INDEX_HORIZONTAL] padding—horizontal padding padding[INDEX_PADDING_LEFT] padding[INDEX_PADDING_TOP] padding[INDEX_PADDING_RIGHT] padding—horizontal / / 2 padding—verticat / / 2 padding—horizontal \ padding[INDEX_PADDING_LEFT] padding—verticat \ padding[INDEX_PADDING_TOP] padding[INDEX_PADDING_BOTTOM] return padding リスト 2.8 の関数ーー pad は、画像にパディングを付加します。パディングを付加したサイズの 画像を作成して、中央にオリジナルの画像を貼り付けます。 第 2 章 CNN で超解像 33

7. TensorFlowはじめました 2

return result—file, padded-file 畳み込み層を通るときに失われるピクセル分、出力サイズは小さくなります。出力プロック が小さくなる分、画像の左端と上端のピクセルが失われます。 関数 --calc-padding を変更して、付加するパディングを 1 プロック ( スライド幅 ) 分加算 します ( リスト 3.7 ) 。 さらにリスト 3.6 の関数ーー srcnn を、パディングを取り除く前に、パディングの量を再計算 するように変更します。 リスト 3.7 : srcnn/eval.py catc—padding(image, stride) : def strideCINDEX_VERTICAL] \ padding—vertical image . height % stride[INDEX—VERTICAL] stride[INDEX_HORIZONTAL] \ image. width % stride[INDEX_HORIZONTAL] padding—horizontal # パディングを追加 padding—vertical + = stride[lNDEX—VERTICAL] padding—horizontat + = stride[INDEX—HORIZONTAL] padding padding[INDEX padding[INDEX paddingC 工 NDEX PADDING_LEFT] PADDING_TOP] padding—horizontal / / 2 padding—vertical / / 2 PADDING_RIGHT] padding[INDEX_PADDING_BOTTOM] return padding padding—horizontat \ padding[INDEX_PADDING_LEFT] padding—vertical \ padding[INDEX_PADD 工 NG—TOP] 図 3.11 は、表 32 の条件で学習した場合の誤差の変化です。 表 3.2 : 学習条件 条件 画像の倍率 (scale) 学習率 (learning-rate ) ニバッチサイズ (batch_size) ステップ数 (max_step) チャンネル数 (CHANNELS) 値 2x 0. 開 1 128 1 開Ⅱ ) 1 ( グレースケール ) 52 第 3 章超解像奮闘記

8. TensorFlowはじめました 2

OS . path . join(dir, MODEL. NAME) dir if not os . path . exists(dir) : os . mkdir(dir) OS . path . j 0i n ( di r , 96s—96dx ・ png OS . path . j Oi n ()i r , '96s-96dx—resuIt. png padded_fite % (name, scate)) resutt file % (name, scale)) lmage . open(image—path) 1 mage image. resize( resized_image (image. width ☆ scale, image . height ☆ scale) , lmage . BICUBIC) if MODEL . CHANNELS resized image resized_image . convert('L') calc—padding(resized—image, stride) padding —pad(resized—image, padding=padding) resized_image —save—image(resized—image, padded—file, padding=padding) extract_btocks(resized—image, stride) btocks —process(blocks, train—dir) btocks —reconstruct(btocks) resutt_image normalize(result_image) ☆ 255 result_image round((MODEL. INPUT_SIZE MODEL . OUTPUT_SIZE) / 2 ) pad pad padding[INDEX_PADDING_LEFT] pad paddingCINDEX_PADDING_TOP] padding[INDEX_PADDING_RIGHT] + = pad padding[INDEX_PADDING_BOTTOM] + = pad —save_image(result image, result—fite, padding=padding) file, padded—file return result 平価 一平価用の画像として、縦横 510PX5 の画像を用意しました ( 図 2.5 ) 。 三ロ 38 第 2 章 CNN で超解像

9. TensorFlowはじめました 2

リスト 3.6 : srcnn/eval.py def _srcnn(image—path, scale, # スライド幅を変更 stride (MODEL. OUTPUT_SIZE, train_dir): MODEL. OUTPUT_SIZE) name, ext = OS. path. sptitext(os. path. basename(image_path)) dir OS . path . dirname(image_path) dir OS . path. join(dir, MODEL . NAME) if not os . path . exists(dir): os . mkdir(dir) padded_fite result fite OS . path . j Oi n ()i r , 96s—96dx ・ png % (name, scale)) OS . path . join(dir, '96s—96dx—resuIt ・ png % (name, scale)) lmage ・ open(image—path) 1 mage resized_image image . resize( (image. width 大 scale, image ・ height ☆ scale) , 工 mage. BICUBIC) if MODEL . CHANNELS resized image 1 : resized—image. convert('L') padding calc—padding(resized—image, stride) resized_image —pad(resized—image, padding=padding) —save—image(resized—image, padded—fite, padding=padding) blocks blocks extract_blocks(resized—image, stride) —process(btocks, train—dir) resutt_image result_image —reconstruct(blocks) _normalize(resutt_image) ☆ 255 # パディングの再計算 pad round ( (MODEL. INPUT_SIZE MODEL. OUTPUT_S 工 (E) / 2 ) padding[ 工 NDEX_PADDING_LEFT] pad padding[ 工 NDEX—PADDING_TOP] pad padding[INDEX_PADDING_RIGHT] + = pad padding[INDEX_PADDING_BOTTOM] + ニ pad —save—image(resutt—image, result—file, padding=padding) 第 3 章超解像奮闘記 51

10. TensorFlowはじめました 2

画像の保存 ( パディングの除去 ) リスト 2.12 の関数 __save_image は、処理済みのデータを画像としてファイルに保存します。 MODEL に定義しているチャンネル数 (CHANNELS) が 1 ( グレースケール ) の場合は配列の 形を変更します 4 。 また、保存の前に付加したパディングを除去 (crop) します。 リスト 2.12 : srcnn/eval.py def —save—image(image, file, padding=None) : mode ' RGB' if MODEL . CHANNELS 1 : 1 mage 1 mage mode np. transpose(image, ( 2 , 0 , 1 ) ) # チャンネル軸を移動 image[@] 工 mage. fromarray(np. uint8(image) , mode=mode) result_image if padding is not None: teft padding[INDEX_PADDING_LEFT] paddingCINDEX_PADDING_TOP] top right result_image. width padding[INDEX_PADDING_RIGHT] bottom result—image . height paddingCINDEX_PADDING_BOTTOM] result_image result—image ・ crop((teft, top, right, bottom)) result—image. convert( ' RGB' ) . save(fite, 実行 ' PNG ' ) これまでのプログラムを組み合わせて画像に超解像処理をします。 リスト 2.13 の関数ー srcnn は、画像 (image_path) をデコードして、 scale 倍したものを、 train ー dir に保存されているパラメーターを使って、超解像処理を実行します。 最後に、モデルから出力されるピクセルの値 (@ . @-1. @) を 255 倍します ( 入力時と逆の (MODEL . INPUT_SIZE, MODEL . INPUT_SIZE) stride _srcnn(image—path, scale, train_dir) : def リスト 2.13 : srcnn/eval.py 処理 ) 。 name, dir ext = OS. path . sptitext()s . path. basename(image—path)) OS . path . di rname(image—path) 第 2 章 CNN で超解像 37