방정식 풀기에서 딥 러닝까지: TensorFlow Python 자습서
게시 됨: 2022-03-11최근 인공 지능의 세계에서 몇 가지 주목할 만한 발전이 있었습니다. 자율 주행 자동차의 대중적인 발전에서 현재 쇼팽의 모방을 구성하는 기계에 이르기까지 또는 비디오 게임을 정말 잘하는 기계에 이르기까지입니다.
이러한 발전의 중심에는 Torch, Caffe 및 Theano가 선두에 있는 딥 러닝 및 기타 기계 학습 모델을 유도하는 데 도움이 되는 여러 도구가 있습니다. 그러나 Google Brain이 2015년 11월 자체 프레임워크인 TensorFlow와 함께 오픈 소스가 된 이후로 이 소프트웨어 라이브러리의 인기가 가장 인기 있는 딥 러닝 프레임워크로 급등하는 것을 보았습니다.
왜 이런 일이 일어났습니까? 그 이유에는 사용 가능한 풍부한 지원 및 문서, 생산 준비, 다양한 장치에 계산을 쉽게 배포할 수 있는 능력, 뛰어난 시각화 도구인 TensorBoard 등이 있습니다.
궁극적으로 TensorFlow는 포괄적이고 유연한 기술 기능 세트와 사용 편의성을 결합합니다.
이 기사에서는 간단한 신경망 구현으로 딥 러닝에 사용하기 전에 기계 학습이 일반적으로 수반하는 것과는 거리가 먼 일반적인 수치 문제를 해결하기 위해 이 도구를 사용하여 이 도구의 역학을 이해하게 될 것입니다.
시작하기 전에
기계 학습 방법에 대한 기본 지식이 있다고 가정합니다. 따라잡기가 필요한 경우 이 매우 유용한 게시물을 확인하십시오.
Python API를 시연할 예정이므로 Numpy에 대한 이해도 도움이 됩니다.
TensorFlow를 설정하려면 여기에 있는 지침을 따르세요.
Windows를 사용하는 경우 작성 당시 Python 2.7이 아닌 Python 3.4 이상을 사용해야 한다는 점에 유의해야 합니다.
그런 다음 준비가 되면 다음을 사용하여 라이브러리를 가져올 수 있어야 합니다.
import tensorflow as tf
TensorFlow 솔루션에 대한 2단계 중 1단계: 그래프 만들기
TensorFlow 프로그램의 구성은 일반적으로 두 가지 주요 단계로 구성되며, 첫 번째 단계는 수행하려는 계산을 설명하지만 실제로 수행하거나 값을 보유하지는 않는 계산 그래프를 작성하는 것입니다.
모든 그래프와 마찬가지로 노드와 간선이 있습니다. 모서리는 n차원 배열을 나타내는 텐서인 텐서를 나타냅니다. 예를 들어 차원(또는 TensorFlow에서 순위)이 0인 텐서는 스칼라, 순위 1은 벡터, 순위 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)
여기에서 우리는 3개의 연산을 만들었습니다. 그 중 2개는 상수 1차원 배열을 생성하기 위한 것입니다.
데이터 유형은 전달된 values 인수에서 유추되거나 dtype
인수로 이를 나타낼 수 있습니다. b
에 대해 이 작업을 수행하지 않았다면 int32
가 유추되었을 것이고 tf.add
로 발생한 오류는 두 가지 다른 유형에 대한 추가를 정의하려고 시도했을 것입니다.
TensorFlow 솔루션에 대한 2/2단계: 작업 실행
그래프가 정의되어 있지만 실제로 계산을 수행하려면(또는 그래프의 일부) TensorFlow 세션을 설정해야 합니다.
sess = tf.Session()
또는 IPython과 같은 대화형 셸에서 세션을 실행하는 경우 다음을 사용합니다.
sess = tf.InteractiveSession()
세션 객체의 run
메소드는 Tensor를 평가하는 한 가지 방법입니다.
따라서 위에서 정의한 덧셈 계산을 평가하기 위해 검색할 Tensor인 'total'을 전달합니다. 이는 tf.add
연산의 출력을 나타냅니다.
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()
그래프와 두 개의 세션을 설정했습니다.
두 세션에서 초기화를 실행한 후(이를 실행하지 않고 변수를 평가하면 오류가 발생함) 한 세션에서만 할당 작업을 실행합니다. 보시다시피 변수 값은 지속되지만 세션 간에는 지속되지 않습니다.
수치 문제를 해결하기 위한 그래프 제공
TensorFlow의 또 다른 중요한 개념은 자리 표시자입니다. 변수가 상태를 유지하는 반면, 자리 표시자는 그래프가 기대할 수 있는 입력과 데이터 유형(및 선택적으로 모양)을 정의하는 데 사용됩니다. 그런 다음 계산을 실행할 때 이러한 자리 표시자를 통해 그래프에 데이터를 공급할 수 있습니다.
TensorFlow 그래프는 우리가 궁극적으로 훈련하고자 하는 신경망과 유사해지기 시작했지만 그 전에 개념을 사용하여 금융 세계의 일반적인 수치 문제를 해결해 보겠습니다.
다음과 같은 방정식에서 y
를 찾고 싶다고 가정합니다.
주어진 v
에 대해( C
및 P
상수 사용).
이것은 시장 가치 v
, 원금 P
, 이표 C
가 반기별로 지급되지만 현금 흐름은 연속 복리로 할인된 채권의 만기 수익률( y
)을 계산하는 공식입니다.
우리는 기본적으로 시행착오를 통해 이와 같은 방정식을 풀어야 하며 y
에 대한 최종 값을 0으로 만들기 위해 이분법을 선택할 것입니다.
먼저 이 문제를 TensorFlow 그래프로 모델링합니다.
C
와 P
는 고정 상수이며 그래프 정의의 일부를 형성합니다. 우리는 y
의 하한과 상한을 다듬는 프로세스를 원합니다. 따라서 이러한 경계( 및 b
로 표시) a
y
(및 b
a
중간점으로 간주)를 추측할 때마다 변경해야 하는 변수의 좋은 후보입니다.
# 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. # eg if the guess results in av 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
와 같은 다른 텐서가 먼저 평가되도록 연쇄 반응이 시작됩니다.
이러한 작업 중 일부는 값을 지정해야 하는 자리 표시자에 의존하므로 실제로 해당 값을 어떻게 입력합니까?
이것은 run
함수 자체의 feed_dict
인수를 통해 수행됩니다.
a_
를 평가하려면 다음과 같이 자리 표시자 v_target
값을 연결합니다.
sess.run(a_, feed_dict={v_target: 100})
0.0을 줍니다.

130의 v_target
을 연결하면 -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에 내장된 몇 가지 추가 기계 학습 작업과 결합하여 간단한 신경망을 훈련할 수 있습니다.
여기서 우리는 데이터 포인트가 특정 영역(원점을 중심으로 하는 반경 0.5의 원)에 속하는지 여부에 따라 2차원 좌표계의 데이터 포인트를 분류하려고 합니다.
물론 이것은 a^2 + b^2 < 0.5
인 경우 주어진 점 (a,b)
를 확인하여 구체적으로 확인할 수 있지만 이 기계 학습 실험의 목적을 위해 대신 a를 전달하고 싶습니다. 훈련 세트: 일련의 무작위 포인트와 이들이 의도한 영역에 속하는지 여부. 이것을 만드는 한 가지 방법은 다음과 같습니다.
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)
다음과 같은 특성을 가진 신경망을 만들 것입니다.
- 이것은 "random_spots"에 포함된 일련의 2차원 벡터를 공급하는 두 개의 노드가 있는 입력 레이어로 구성됩니다. 이것은 훈련 데이터를 기다리는 자리 표시자로 표시됩니다.
- 출력 레이어에도 두 개의 노드가 있으므로 일련의 교육 레이블("is_inside_circle")을 스칼라의 자리 표시자에 입력한 다음 해당 값을 원-핫 2차원 벡터로 변환해야 합니다.
- 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를 나타내므로 실행하려는 epoch 수에 대해 반복됩니다. 정보 제공을 위해 "손실" 텐서와 같은 그래프의 다른 부분을 실행할 수 있습니다.
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
텐서를 실행하여 학습자가 긍정적으로 분류된 포인트를 포함하는 영역을 구상하는 방법에 대한 아이디어를 얻을 수 있습니다. 훈련 세트의 크기, 학습률 및 기타 매개변수를 가지고 놀면서 우리가 의도한 원에 얼마나 근접할 수 있는지 확인하는 것은 가치가 있습니다.
학습률: 0.01
에포크: 1000
학습률: 0.01
에포크: 1000
학습률: 0.01
에포크: 10000
학습률: 0.001
에포크: 10000
마무리
이것은 증가된 training set 또는 epoch 양이 좋은 학습자를 보장하지 않는다는 좋은 교훈입니다. learning rate는 적절하게 조정되어야 합니다.
이 데모가 TensorFlow의 핵심 원칙에 대한 좋은 통찰력을 제공하고 더 복잡한 기술을 구현하기 위한 견고한 토대를 제공하기를 바랍니다.
Tensorboard와 같은 개념이나 GPU를 통한 모델 교육과 같은 개념은 다루지 않았지만 TensorFlow 문서에서 이에 대해 잘 설명하고 있습니다. 이 강력한 프레임워크를 사용하여 흥미진진한 딥 러닝 작업을 빠르게 처리하는 데 도움이 되는 다양한 레시피를 문서에서 찾을 수 있습니다!