본문 바로가기

개발/Python(파이썬)

TensorFlow Python 자습서

최근 인공 쇼트 (인공 지능) 세계에서 주목할만한 발전이있었습니다. 자체 추진 자동차로 진행된 많은 진전에서 쇼팽 모방을 구성 하거나 현재 비디오 게임에 능숙한 기계 입니다.

이러한 진보의 중심에는 Torch, Caffe 및 Theano와 함께 심층 학습 및 기타 기계 학습 모델을 도출하는 데 도움 이되는 다양한 도구가 있습니다. 그러나 Google Brain은 2015 년 11 월 자체 프레임 워크 인 TensorFlow를 통해 오픈 소스로 접어 들었으므로이 소프트웨어 라이브러리의 인기가 급증하면서 가장 인기있는 심층 학습 프레임 워크가되었습니다.

왜 이런 일이 일어 났습니까? 그 이유에는 풍부한 지원 및 문서, 생산 준비성, 다양한 장치에 대한 계산 배포 용이성 및 탁월한 시각화 도구 인 TensorBoard가 있습니다.

궁극적으로 TensorFlow는 포괄적이고 유연한 기술 기능을 사용 편의성과 결합시킵니다.

이 기사에서는 간단한 신경망 구현으로 깊은 학습에 사용하기 전에 일반적인 수학 문제를 해결하기 위해이 도구의 메커니즘을 이해하게됩니다.

시작하기 전에

기계 학습 방법에 대한 기본 지식이 가정됩니다. 따라 잡기가 필요하면이 유용한 게시물을 확인하십시오 .

파이썬 API를 시연 할 것이므로, Numpy에 대한 이해 또한 도움이됩니다.

TensorFlow를 설정하려면 여기에 있는 지침을 따르십시오 .

Windows를 사용하는 경우, 작성 당시에 2.7이 아닌 Python 3.4+를 사용해야한다는 점에 유의해야합니다.

그런 다음 준비가되면 다음을 사용하여 라이브러리를 가져올 수 있습니다.

import tensorflow as tf

TensorFlow 솔루션에 2 단계 중 1 단계 : 그래프 만들기

TensorFlow 프로그램의 구성은 일반적으로 두 가지 주요 단계로 이루어지며, 먼저 계산 그래프를 작성하여 수행하려는 계산을 설명하지만 실제로 수행하거나 계산하지 않습니다.

어떤 그래프와 마찬가지로 노드와 모서리가 있습니다. 가장자리는 텐서를 나타내며 텐서는 n 차원 배열을 나타냅니다. 예를 들어, 차원이있는 텐서 (또는 TensorFlow가 말하는 언어의 순위) 0은 스칼라이고 벡터는 1 위, 벡터는 2 위, 매트릭스는 2 위 등입니다.

노드는 필요한 경우 텐서를 입력으로 취하는 출력 텐서를 생성하는 연산을 나타냅니다. 이러한 연산에는 덧셈 ( tf.add), 행렬 곱셈 ( tf.matmul) 및 상수 생성 ( tf.constant)이 포함됩니다.

자, 우리의 첫 번째 그래프를 위해 이들 중 몇 가지를 결합합시다.

a = tf.constant([2.5, 2])
b = tf.constant([3, 6], dtype=tf.float32)
total = tf.add(a, b)

여기서는 세 가지 연산을 만들었습니다.이 중 두 개는 상수 1-d 어레이를 생성합니다.

데이터 형식은 전달 된 values ​​인수에서 유추됩니다. 또는 인수를 사용하여 이러한 데이터 형식을 나타낼 수 있습니다 dtype나는이에 대한 일을하지 않았다면 b, 다음은 int32추정 된 것과 같이 던져 오류는 tf.add두 가지 유형에 추가를 정의하기 위해 노력했을 것이다.

TensorFlow 솔루션에 2 단계 중 2 단계 : 작업 실행

그래프가 정의되었지만 실제 계산을하기 위해 TensorFlow 세션을 설정해야합니다.

sess = tf.Session()

또는 IPython과 같은 대화 형 셸에서 세션을 실행하는 경우 다음을 사용합니다.

sess = tf.InteractiveSession()

run세션 객체 의 메소드는 Tensor를 평가하는 한 가지 방법입니다.

따라서 위에 정의 된 추가 계산을 평가하기 위해 tf.add연산 의 출력을 나타내는 'total', 검색 할 Tensor를 전달합니다 .

print(sess.run(total)) # [ 5.5  8. ]

이 시점에서 TensorFlow의 Variable 클래스를 소개합니다. 상수는 그래프 정의의 고정 된 부분이지만 변수는 업데이트 될 수 있습니다. 클래스 생성자는 초기 값을 요구하지만, 심지어 변수는 다른 연산이 수행되기 전에 명시 적으로 초기화하는 연산을 필요로합니다.

변수는 특정 세션에서 그래프의 상태를 유지하므로 변수를 더 잘 이해하기 위해 동일한 그래프를 사용하여 여러 세션에서 어떤 일이 발생하는지 관찰해야합니다.

# Create a variable with an initial value of 1
some_var = tf.Variable(1)

# Create op to run variable initializers
init_op = tf.global_variables_initializer()
 
# Create an op to replace the value held by some_var to 3
assign_op = some_var.assign(3)
 
# Set up two instances of a session
sess1 = tf.Session()
sess2 = tf.Session()

# Initialize variables in both sessions
sess1.run(init_op)
sess2.run(init_op)
print(sess1.run(some_var)) # Outputs 1

# Change some_var in session1
sess1.run(assign_op)
print(sess1.run(some_var)) # Outputs 3
print(sess2.run(some_var)) # Outputs 1

# Close sessions
sess1.close()
sess2.close()

우리는 그래프와 두 개의 세션을 설정했습니다.

두 세션에서 초기화를 실행 한 후 (이 작업을 실행하지 않고 변수를 평가하면 오류가 발생 함) 하나의 세션에서만 assign op를 실행합니다. 볼 수 있듯이 가변 값은 지속되지만 세션 전체에서는 그렇지 않습니다.

수치 문제 해결을위한 그래프 공급

TensorFlow의 또 다른 중요한 개념은 자리 표시 자입니다. 변수가 상태를 유지하는 반면, 자리 표시자는 그래프에서 예상 할 수있는 입력 및 데이터 유형 (및 선택적으로 모양)을 정의하는 데 사용됩니다. 그런 다음 계산을 실행할 때 이러한 자리 표시자를 통해 그래프에 데이터를 공급할 수 있습니다.

TensorFlow 그래프는 우리가 결국 훈련하기를 원하는 신경 네트워크와 유사 해지기 시작했지만, 그 전에는 개념을 사용하여 금융 세계의 일반적인 수치 문제를 해결할 수 있습니다.

우리 y가 다음과 같은 방정식 을 찾고 싶다고합시다 :

v = Ce -0.5y + Ce -y + Ce- 1.5y + (C + P) e- 2y

주어진 v주어진 C과 P상수).

이것은 y시장 가치 v, 원금 P및 쿠폰을 C반년마다 지불 하는 채권의 만기 수익률을 계산하는 공식 이지만 연속적인 컴 파운딩으로 할인 된 현금 흐름을 사용합니다.

우리는 기본적으로 시행 착오를 통해 방정식을 풀어야하며 최종 값을 0으로 만들기 위해 이분법을 선택합니다 y.

먼저이 문제를 TensorFlow 그래프로 모델화합니다.

C및 P상수하고 그래프 정의의 형태 부분을 고정한다. 우리는의 상한선과 하한선을 다듬는 과정을 원합니다 y그러므로이 경계 ( a및 로 표시 b)는 각각의 추측 이후에 변경되어야하는 변수에 대한 좋은 후보입니다 ya및 의 중간 점으로 취해진 다 b).

# Specify the values our constant ops will output
C = tf.constant(5.0)
P = tf.constant(100.0)

# We specify the initial values that our lower and upper bounds will be when initialised.
# Obviously the ultimate success of this algorithm depends on decent start points
a = tf.Variable(-10.0)
b = tf.Variable(10.0)
 
# We expect a floating number to be inserted into the graph
v_target = tf.placeholder("float")
 
# Remember the following operations are definitions,
# none are carried out until an operation is evaluated in a session!
y = (a+b)/2
v_guess = C*tf.exp(-0.5*y) + C*tf.exp(-y) + C*tf.exp(-1.5*y) + (C + P)*tf.exp(-2*y)
 
# Operations to set temporary values (a_ and b_) intended to be the next values of a and b.
# e.g. if the guess results in a v greater than the target v,
# we will set a_ to be the current value of y
a_ = tf.where(v_guess > v_target, y, a)
b_ = tf.where(v_guess < v_target, y, b)
 
# The last stage of our graph is to assign the two temporary vals to our variables
step = tf.group( a.assign(a_), b.assign(b_) )

이제는 특정 세션에 대해 평가할 수있는 연산 및 변수의 목록을 갖게되었습니다. 이러한 작업 중 일부는 이렇게 말, 실행, 실행하기 위해 다른 작업에 의존하는 v_guess등 다른 텐서를 가지고 연쇄 반응을 설정합니다 C하고 P, 먼저 평가되어야한다.

이러한 연산 중 일부는 값을 지정해야하는 자리 표시 자에 의존하므로 실제로이 값을 어떻게 입력합니까?

이것은 함수 자체 의 feed_dict인수를 통해 run수행됩니다.

평가 a_하려면 v_target다음과 같이 자리 표시 자 값을 연결합니다 .

sess.run(a_, feed_dict={v_target: 100})

우리에게 0.0을주었습니다.

A의 플러그 v_target(130)의 우리는 -10.0를 얻을.

이것은 실제로 모든 다른 작업을 전제 조건으로 수행해야하며 사실상 전체 그래프를 실행하는 "단계"작업입니다. 또한 실제 세션을 실제로 변경하는 작업이기도합니다. 따라서, 우리는 단계를 실행 될수록 우리는 점차적으로 우리의 변수를 슬쩍 찌르다 a와 b의 실제 값을 향해 y.

그래서 v방정식에서 우리 의 가치 가 95와 같다고 가정 해 봅시다. 세션을 설정하고 그 위에 그래프를 100 번 실행 해 봅시다.

# Set up a session and initialize variables
sess = tf.Session()
tf.global_variables_initializer().run()
# Run the step operation (and therefore whole graph) 100 times
for i in range (100):
	sess.run(step, feed_dict={v_target:95})

y지금 우리가 텐서 를 평가한다면 , 우리는 바람직한 답을 닮은 것을 얻습니다.

print(sess.run(y)) # 0.125163

신경망

이제 TensorFlow의 메커니즘에 대해 이해 했으므로 TensorFlow에 내장 된 몇 가지 추가 기계 학습 작업과 함께이 작업을 수행하여 간단한 신경 네트워크를 학습 할 수 있습니다.

여기서 우리는 데이터 포인트가 특정 지역 내에 있는지 여부에 따라 2 차원 좌표계에서 원점을 기준으로 반경 0.5의 원을 분류하고자합니다.

물론, 이것은 구체적으로 단지 특정 지점에 대한 검사에 의해 확인 될 수 (a,b)있는 경우 a^2 + b^2 < 0.5, 그러나이 기계 학습 실험의 목적을 위해, 우리는 대신 훈련 세트를 전달하고 싶습니다 : 임의 일련의 점을 그들이에 해당 여부를 우리 의도 된 영역. 이 방법을 만드는 방법은 다음과 같습니다.

import numpy as np
NO_OF_RANDOM_POINTS = 100
CIRCLE_RADIUS = 0.5
random_spots = np.random.rand(NO_OF_RANDOM_POINTS, 2) * 2 - 1
is_inside_circle = (np.power(random_spots[:,0],2) + np.power(random_spots[:,1],2) < CIRCLE_RADIUS).astype(int)

우리는 다음과 같은 특성을 가진 신경망을 만들 것입니다.

  1. 이것은 두 개의 노드가있는 입력 레이어로 구성되며 "random_spots"내에 포함 된 일련의 2 차원 벡터를 공급합니다. 이는 교육 자료를 기다리는 자리 표시 자로 나타납니다.
  2. 출력 레이어도 두 개의 노드를 가지므로 일련의 학습 레이블 ( "is_inside_circle")을 스칼라의 자리 표시 자에 공급 한 다음 해당 값을 핫 한 2 차원 벡터로 변환해야합니다.
  3. 우리는 3 개의 노드로 구성된 하나의 숨겨진 계층을 가지므로, 우리는 가중치 행렬 및 바이어스 벡터에 변수를 사용해야합니다. 이는 이들이 학습을 수행 할 때 수정해야하는 값이기 때문입니다.
INPUT_LAYER_SIZE = 2
HIDDEN_LAYER_SIZE = 3
OUTPUT_LAYER_SIZE = 2
 
# Starting values for weights and biases are drawn randomly and uniformly from  [-1, 1]
# For example W1 is a matrix of shape 2x3
W1 = tf.Variable(tf.random_uniform([INPUT_LAYER_SIZE, HIDDEN_LAYER_SIZE], -1, 1))
b1 = tf.Variable(tf.random_uniform([HIDDEN_LAYER_SIZE], -1, 1))
W2 = tf.Variable(tf.random_uniform([HIDDEN_LAYER_SIZE, OUTPUT_LAYER_SIZE], -1, 1))
b2 = tf.Variable(tf.random_uniform([OUTPUT_LAYER_SIZE], -1, 1))
# Specifying that the placeholder X can expect a matrix of 2 columns (but any number of rows)
# representing random spots
X = tf.placeholder(tf.float32, [None, INPUT_LAYER_SIZE])
# Placeholder Y can expect integers representing whether corresponding point is in the circle
# or not (no shape specified)
Y = tf.placeholder(tf.uint8)
# An op to convert to a one hot vector
onehot_output = tf.one_hot(Y, OUTPUT_LAYER_SIZE)

그래프의 정의를 완성하기 위해 우리는 더 나은 분류 기준에 도달하기 위해 변수를 훈련하는 데 도움이되는 몇 가지 연산을 정의합니다. 여기에는 행렬 계산, 활성화 함수 및 최적화가 포함됩니다.

LEARNING_RATE = 0.01
# Op to perform matrix calculation X*W1 + b1
hidden_layer = tf.add(tf.matmul(X, W1), b1)
# Use sigmoid activation function on the outcome
activated_hidden_layer = tf.sigmoid(hidden_layer)
# Apply next weights and bias (W2, b2) to hidden layer and then apply softmax function
# to get our output layer (each vector adding up to 1)
output_layer = tf.nn.softmax(tf.add(tf.matmul(activated_hidden_layer, W2), b2))
# Calculate cross entropy for our loss function
loss = -tf.reduce_sum(onehot_output * tf.log(output_layer))
# Use gradient descent optimizer at specified learning rate to minimize value given by loss tensor
train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(loss)

그래프를 설정하고 나면 세션을 설정하고 "train_step"을 실행합니다 (전제 조건을 실행 함). 이러한 작업 중 일부는 자리 표시자를 사용하기 때문에 값을 제공해야합니다. 이 훈련 단계는 학습 알고리즘에서 하나의 에포크를 나타내며, 실행하려는 에포크의 수에 걸쳐 반복됩니다. 정보를 얻기 위해 "손실"텐서와 같은 그래프의 다른 부분을 실행할 수 있습니다.

EPOCH_COUNT = 1000
sess = tf.Session()
tf.global_variables_initializer().run()
for i in range(EPOCH_COUNT):
    if i%100 == 0:
    	print('Loss after %d runs: %f' % (i, sess.run(loss, feed_dict={X: random_spots, Y: is_inside_circle})))
	sess.run(train_step, feed_dict={X: random_spots, Y: is_inside_circle})
print('Final loss after %d runs: %f' % (i, sess.run(loss, feed_dict={X: random_spots, Y: is_inside_circle})))

일단 우리가 알고리즘을 훈련하면, 우리는 한 지점을 먹여서 다음과 같이 신경망의 출력을 얻을 수 있습니다 :

sess.run(output_layer, feed_dict={X: [[1, 1]]}) # Hopefully something close to [1, 0]
sess.run(output_layer, feed_dict={X: [[0, 0]]}) # Hopefully something close to [0, 1]

출력 벡터의 첫 번째 멤버가 0.5보다 크면 그 점을 원에서 벗어난 것으로 분류 할 수 있습니다.

output_layer많은 점들에 대해 텐서를 실행함으로써 학습자가 긍정적으로 분류 된 점들을 포함하는 영역을 어떻게 상상하는지에 대한 아이디어를 얻을 수 있습니다. 교육 세트의 크기, 학습 속도 및 기타 매개 변수를 사용하여 우리가 의도 한 원에 얼마나 가까이 다가 갈 수 있는지 알아볼 가치가 있습니다.