추론 Inference
inference() 함수는, output 예측이 포함될 수도 있는 텐서를 리턴하는데 필요한 만큼, 그래프를 작성합니다.
The inference() function builds the graph as far as needed to return
the tensor that would contain the output predictions.
inference() 함수는, 이미지 플레이스홀더를 입력으로 취하고 그것 위에, output
logits를 규정하는 10개 노드 선형 층이 뒤따르는, ReLu activation를 가진 한 쌍의 모두 연결된 층들을 구축합니다.
It takes the images placeholder as input and builds on top of it a pair of
fully connected layers with ReLu activation followed by a ten node linear layer
specifying the output logits.
각 층은, 해당 scope안에서 생성된 아이템에 대한 prefix로 행동하는, 유일한 tf.name_scope 아래에 생성됩니다.
Each layer is created beneath a unique tf.name_scope that acts as a prefix to the items created within
that scope.
with tf.name_scope('hidden1') as scope:
정의된 scope 내에서, 이들 각 층이 사용할 가중치와 biases가, 그들의 원하는 형태로, tf.Variable 인스턴스 안으로 생성됩니다:
Within the defined scope, the weights and biases to be used by each of these
layers are generated into tf.Variable instances, with their desired shapes:
weights = tf.Variable(
tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),
name='weights')
biases = tf.Variable(tf.zeros([hidden1_units]),
name='biases')
예를 들어, hidden1 scope 아래에서 이들이 생성될 때, 가중치 변수에 부여된 유일한 이름은 "hidden1/weights"이 될 것입니다.
When, for instance, these are created under the hidden1 scope, the
unique name given to the weights variable would be "hidden1/weights".
각 변수에는 그 구축의 일부로 초기화자(initializer) ops가 주어집니다.
Each variable is given initializer ops as part of their construction.
대부분의 이러한 공통적인 경우, 가중치는 tf.truncated_normal 로 초기화되고, 층으로부터 가중치가 연결되는 층 안에서 단위의 숫자를 표현하는 첫째 dim을 가진, 그리고 가중치가 연결되는 층 안에서 단위의 숫자를 표현하는 두 번째 dim을 가진, 그들의 2-D tensor 형상이 주어집니다.
In this most common case, the weights are initialized with the tf.truncated_normal and given their shape of a 2-D tensor
with the first dim representing the number of units in the layer from which the
weights connect and the second dim representing the number of units in the
layer to which the weights connect.
첫째 층에서, 소위 hidden1, 차원들은 [IMAGE_PIXELS, hidden1_units]인데, 그 이유는 가중치가 이미지 입력들을 hidden1층에 연결시키고 있기 때문입니다.
For the first layer, named hidden1, the dimensions are [IMAGE_PIXELS,
hidden1_units] because the weights are connecting the image inputs to the
hidden1 layer.
tf.truncated_normal initializer는 주어진 mean과 표준편차를 가진 랜덤 분포를 생성시킵니다.
The tf.truncated_normal initializer generates a random distribution with a given mean and standard deviation.
그런 다음 biases는 그들이 모두 0 값으로 시작하는 것을 보장하기 위하여 tf.zeros로 초기화 되며, 그들의 형태는 그들이 연결되는 층 안에서 단순히 단위의 숫자 입니다.
Then the biases are initialized with tf.zeros to ensure they start with all zero values, and
their shape is simply the number of units in the layer to which they connect.
그런 다음, 그래프의 3개의 primary ops(감춰진 층의 tf.matmul을 감싸는 2개의 tf.nn.relu ops, 로짓 용 1개의 extratf.matmul)가 차례로 생성되는데, 이들은 각각의 입력 placeholders 또는 이전 층의 출력 텐서에 연결된 별도의 tf.Variable 인스턴스를 갖고 있습니다.
The graph's three primary ops -- two tf.nn.relu ops wrapping tf.matmul for the hidden layers and one
extratf.matmul for the logits -- are then created, each in turn, with
separate tf.Variable instances connected to each of the input
placeholders or the output tensors of the previous layer.
hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
logits = tf.matmul(hidden2, weights) + biases
최종적으로, 출력을 포함할 로짓(logits) 텐서가 리턴됩니다.
Finally, the logits tensor that will contain the output is returned.
Loss
loss() 함수는
필요한
손실
ops를 추가하여 그래프를
구축합니다.
The loss() function further builds the graph by adding the required
loss ops.
먼저, labels_placeholer로부터의 값을 1-hot 값의 텐서로 인코드합니다.
First, the values from
the labels_placeholder are encoded as a tensor of 1-hot values.
예를 들어, 라벨의 값이 '3'이라면 다음과 같이 변환됩니다: [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
For example, if the class identifier is '3'
the value is converted to: [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
batch_size = tf.size(labels)
labels = tf.expand_dims(labels, 1)
indices = tf.expand_dims(tf.range(0, batch_size, 1), 1)
concated = tf.concat(1, [indices, labels])
onehot_labels = tf.sparse_to_dense(
concated, tf.pack([batch_size, NUM_CLASSES]), 1.0, 0.0)
그런 다음, inference() 함수에서 나온 출력 logits와 1-hot 레이블을 비교하기 위해 tf.nn.softmax_cross_entropy_with_logits op를 추가합니다.
A tf.nn.softmax_cross_entropy_with_logits op is then added to compare the output
logits from the inference() function and the 1-hot labels.
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits, onehot_labels, name='xentropy')
그 후, 뱃치 차원(batch
dimension, 첫 번째 차원)에 대해 교차 엔트로피(cross
entropy)의 평균값을 취하여 총 손실을 얻기 위해 tf.reduce_mean를 사용합니다.
It then uses tf.reduce_mean to average the cross entropy values
across the batch dimension (the first dimension) as the total loss.
loss = tf.reduce_mean(cross_entropy, name='xentropy_mean')
그러면 손실 값이 포함된 텐서가 반환됩니다.
And the tensor that will then contain the loss value is returned.
Note: 교차 엔트로피는 정보 이론에서 나온 개념으로, 참 값을 알고 있을 때 NN 예측 결과로 나온 값을 얼마나 신뢰할 수 없는지 정량적으로 기술하는 것입니다.
더 많은 정보를 원하시면 시각 정보 이론에 대한 블로그 글을 읽어보세요 (http://colah.github.io/posts/2015-09-Visual-Information/)
Note: Cross-entropy is an idea from information theory that allows us to
describe how bad it is to believe the predictions of the neural network, given
what is actually true. For more information, read the blog post Visual
Information Theory (http://colah.github.io/posts/2015-09-Visual-Information/)
훈련시키기 Training
training() 함수는 내리막기울기(gradient
descent)를 통해 손실을 최소화 하는데 필요한 op를 추가 시킵니다.
The training() function adds the operations needed to minimize the
loss via gradient descent.
먼저, loss() 함수에서 생긴 손실 텐서를 tf.scalar_summary (tf.scalar_summary은 요약값 (summary values)을 생성하는 op)로 넘기는데, SummaryWriter(아래 참조)와 함께 사용하면 요약값을 이벤트 파일에 쓸 수 있습니다.
Firstly, it takes the loss tensor from
the loss() function and hands it to a tf.scalar_summary, an op for generating summary values into
the events file when used with a SummaryWriter (see below).
이 경우, 요약이 작성될 때마다 손실의 스냅샷 값(snapshot
value of the loss)이 나옵니다.
In this case, it will emit the snapshot value of the loss every time the
summaries are written out.
tf.scalar_summary(loss.op.name,
loss)
다음으로, 요청된 학습 속도(learning
rate)에 따라 기울기를 적용하는 tf.train.GradientDescentOptimizer를 인스턴스화 합니다.
Next, we instantiate a tf.train.GradientDescentOptimizer responsible for applying gradients with
the requested learning rate.
optimizer =
tf.train.GradientDescentOptimizer(FLAGS.learning_rate)
전역(global) 훈련 단계를 세는 카운터(counter) 변수를 하나 만들고, 시스템의 훈련 가능한 가중치 와 카운터 변수를 갱신하기 위해 minimize()를 사용합니다.
We then generate a single variable to
contain a counter for the global training step and the minimize() op is used to both update the trainable
weights in the system and increment the global step.
minimize()는 관습적으로 train_op라고 하며, 1개의 완전한 훈련 단계를 이끌어내기 위해 TensorFlow 세션이 가동되어야 합니다(아래를 참조하세요).
This is, by convention, known as the train_op and is what must be run
by a TensorFlow session in order to induce one full step of training (see
below).
global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
훈련 op의 출력이 포함된 텐서가 반환됩니다.
The tensor containing the outputs of the training op is returned.
'TensorFlow' 카테고리의 다른 글
TensorFlow Mechanics 101 (3) (0) | 2016.04.30 |
---|---|
TensorFlow Mechanics 101 (1) (0) | 2016.04.30 |
CNN (3) (0) | 2016.04.30 |
CNN (2) (0) | 2016.04.30 |
CNN (1) (0) | 2016.04.30 |
댓글