質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

with構文の必要性がわからない

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,725
退会済みユーザー

退会済みユーザー

CIFAR-10形式のデータセットを読み込むプログラムを書いています。

# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf

NUM_CLASSES = 10

def _get_weights(shape,stddev=1.0):
  var = tf.get_variable(
      'weights',
      shape,
      initializer=tf.truncated_normal_initializer(stddev=stddev)
  )
  return var

def _get_biases(shape,value=0.0):
  var = tf.get_variable(
      'biases',
      shape,
      initializer=tf.constant_initializer(value)
  )
  return var

def inference(image_node):
   #  conv1
   with tf.variable_scope('conv1') as scope:
     weights = _get_weights(shape=[5,5,3,64],stddev=1e-4)
     conv = tf.nn.conv2d(image_node,weights,[1,1,1,1],padding='SAME')
     biases = _get_biases([64],value=0.1)
     bias = tf.nn.bias_add(conv,biases)
     conv1 = tf.nn.relu(bias,name=scope.name)

   #  pool
   pool1 = tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME',name='pool1')

   #  conv2
   with tf.variable_scope('conv2') as scope:
     weights = _get_weights(shape=[5,5,64,64],stddev=1e-4)
     conv = tf.nn.conv2d(pool1,weights,[1,1,1,1],padding='SAME')
     biases = _get_biases([64],value=0.1)
     bias = tf.nn.bias_add(conv,biases)
     conv2 = tf.nn.relu(bias,name=scope.name)

   #  pool2
   pool2 = tf.nn.max_pool(conv2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME',name='pool2')
   reshape = tf.reshape(pool2,[1,-1])
   dim = reshape.get_shape()[1].value

   #  fc3
   with tf.variable_scope('fc3') as scope:
       weights = _get_weights(shape=[dim,384],stddev=0.04)
       biases = _get_biases([384],value=0.1)
       fc3 = tf.nn.relu(
           tf.matmul(reshape,weights) + biases,
           name=scope.name
       )

   #  fc4
   with tf.variable_scope('fc4') as scope:
       weights = _get_weights(shape=[384,192],stddev=0.04)
       biases = _get_biases([192],value=0.1)
       fc4 = tf.nn.relu(tf.matmul(fc3,weights) + biases,name=scope.name)

   #   output
   with tf.variable_scope('output') as scope:
       weights = _get_weights(shape=[192,NUM_CLASSES],stddev=1/192.0)
       biases = _get_biases([NUM_CLASSES],value=0.0)
       logits = tf.add(tf.matmul(fc4,weights),biases,name='logits')


   return logits

このコードに所々に出てくるwith構文の必要性がわかりません。
私は、with構文はファイルオープン・クローズの時に使い、with構文を使わない書き方の時に使うclose()メソッドを書かなくてもいい点が便利、という解釈をしています。
http://reiki4040.hatenablog.com/entry/20130331/1364723288

しかし、上記のコードのwith構文はファイルオープン・クローズに関係あるわけではないので、どうしてwith構文を使っているのかわかりません。
私のwith構文の解釈が間違っているのでしょうか?
解説をお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

8.5. with 文

with 文は、ブロックの実行を、コンテキストマネージャによって定義されたメソッドでラップするために使われます (with文とコンテキストマネージャ セクションを参照してください)。これにより、よくある try...except...finally 利用パターンをカプセル化して便利に再利用することができます。

close() を省略する楽な書き方ではありません。例外が起こっても必ず close() のような最終処理が呼ばれるようにするための仕組みです。
ファイルのオープン・クローズだけでなく、コンテキストマネージャは様々な場面で使います。

追記

どこからどこまで解説すればいいのかわかりませんが、解決してないようなのでやってみましょうか。

まずは「例外」というものがあるのをご存知ですか?

例えば 3 / i という計算を行うとします。通常はこれでいいのですが、i が 0 の場合、答えは未定義になってしまいます。ですから、i が 0 にならないよう、事前にチェックしてはねておかなければいけません。

ところがプログラマーが i が 0 になる場面を想像していなかったとします。この時、C などの昔の言語であれば、エラーメッセージを出して停止するか、または暴走していました。

このため、例外的なデータをチェックするコードが何重にも書かれることになり、主なアルゴリズムがそれに隠れて読みにくくなっていました。

これを改善するために生まれたのが例外と例外処理です。

不正な処理が行われると、例外が発生します。例外のデフォルトの動作は、メッセージを出し、以降の関連する処理を必要なところまでスキップすることです。

例外が起きそうなところを try catch ブロックで囲むと、このデフォルトの動作を上書きできます。

これによって事前に何重ものチェックをしなくても、実際に不正なデータが入力された段階で一度のチェックで済ませることができるようになり、コードの可読性が向上します。

また、finally を使えば、スキップしてはいけない部分を明示的に指示できます。これにより、例えばオープンしたファイルが必ずクローズされるよう保証できます。

この try catch finally ブロックはプログラマーが書く必要がありますが、多くの場合、同じ処理を書くことになります。例えば、ファイルを開いた時には必ず finally で閉じます。

このようにオブジェクトによって例外処理が決まっているなら、オブジェクト自身が処理方法を知っていればいいじゃないかという考えが出てきます。そうすれば何度も何度も同じことを書かずに済みます。

一連の文から成る一定の処理を文脈(コンテキスト)と言いますが、この例外処理を行う文脈(コンテキスト)を管理(マネージメント)するのがコンテキストマネージャーです。

コンテキストマネージャーとは、例外が起こった時の処理方法を知っているオブジェクトのことです。
具体的には、__enter__ と __exit__ を実装したオブジェクトのことです。

__enter__ は with 文に入る時に呼ばれ、初期化を担当します。__exit__ は出るときに呼ばれます。出る時というのは例外が起こった時も含みます。したがって __exit__ に書くべきは finally ブロックに書いていた処理です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/12 12:42

    丁寧な説明をありがとうございます。1点まだわからない場所があるのですが、例えば
    with tf.variable_scope('fc3') as scope: で、この全体のコード中でfc3をどこにも定義していません。このfc3や全体のコード中の'fc4'や'output'などのwith~~()の()の中身はどこからきているのでしょうか?この中身はどういう役割なのでしょうか?

    キャンセル

  • 2017/04/12 12:46

    そこで初めてスコープ名として定義されているのですが、それはまた別の質問です。

    キャンセル

  • 2017/04/12 12:47

    なるほど!丁寧にありがとうございました。

    キャンセル

0

TensorFlow上の変数(Variable)を区別するためです。TensorFlowでは名前空間(scope)を与えて各レイヤの変数を区別しています。詳しくは、以下をご覧ください。
https://www.tensorflow.org/programmers_guide/variable_scope

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

withはenterexitというメソッド(?)でオブジェクトに関する開始と終了の処理を挟める便利な仕組みと理解すると良いです。

with XYZ() as xyz: となっていればここでxyzに関して何らかの開始処理が行われて、なおかつこのブロックを抜けるときには対になる終了処理が必ず走ります。

with tf.variable_scope('conv1') as scope: も同じです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る