강의영상

imports

import tensorflow as tf
import numpy as np
tf.config.experimental.list_physical_devices('GPU')
2022-03-21 13:59:52.470472: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:939] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

지난강의 보충

- 예제: (2,3,4), (2,3,4), (2,3,4)

(예시1) (2,3,4), (2,3,4), (2,3,4) $\to$ (6,3,4)

a=tf.reshape(tf.constant(range(2*3*4)),(2,3,4))
b=-a
c=2*a
a,b,c
(<tf.Tensor: shape=(2, 3, 4), dtype=int32, numpy=
 array([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],
 
        [[12, 13, 14, 15],
         [16, 17, 18, 19],
         [20, 21, 22, 23]]], dtype=int32)>,
 <tf.Tensor: shape=(2, 3, 4), dtype=int32, numpy=
 array([[[  0,  -1,  -2,  -3],
         [ -4,  -5,  -6,  -7],
         [ -8,  -9, -10, -11]],
 
        [[-12, -13, -14, -15],
         [-16, -17, -18, -19],
         [-20, -21, -22, -23]]], dtype=int32)>,
 <tf.Tensor: shape=(2, 3, 4), dtype=int32, numpy=
 array([[[ 0,  2,  4,  6],
         [ 8, 10, 12, 14],
         [16, 18, 20, 22]],
 
        [[24, 26, 28, 30],
         [32, 34, 36, 38],
         [40, 42, 44, 46]]], dtype=int32)>)
tf.concat([a,b,c],axis=0)
<tf.Tensor: shape=(6, 3, 4), dtype=int32, numpy=
array([[[  0,   1,   2,   3],
        [  4,   5,   6,   7],
        [  8,   9,  10,  11]],

       [[ 12,  13,  14,  15],
        [ 16,  17,  18,  19],
        [ 20,  21,  22,  23]],

       [[  0,  -1,  -2,  -3],
        [ -4,  -5,  -6,  -7],
        [ -8,  -9, -10, -11]],

       [[-12, -13, -14, -15],
        [-16, -17, -18, -19],
        [-20, -21, -22, -23]],

       [[  0,   2,   4,   6],
        [  8,  10,  12,  14],
        [ 16,  18,  20,  22]],

       [[ 24,  26,  28,  30],
        [ 32,  34,  36,  38],
        [ 40,  42,  44,  46]]], dtype=int32)>

(예시2) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,9,4)

tf.concat([a,b,c],axis=1)
<tf.Tensor: shape=(2, 9, 4), dtype=int32, numpy=
array([[[  0,   1,   2,   3],
        [  4,   5,   6,   7],
        [  8,   9,  10,  11],
        [  0,  -1,  -2,  -3],
        [ -4,  -5,  -6,  -7],
        [ -8,  -9, -10, -11],
        [  0,   2,   4,   6],
        [  8,  10,  12,  14],
        [ 16,  18,  20,  22]],

       [[ 12,  13,  14,  15],
        [ 16,  17,  18,  19],
        [ 20,  21,  22,  23],
        [-12, -13, -14, -15],
        [-16, -17, -18, -19],
        [-20, -21, -22, -23],
        [ 24,  26,  28,  30],
        [ 32,  34,  36,  38],
        [ 40,  42,  44,  46]]], dtype=int32)>

(예시3) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,12)

tf.concat([a,b,c],axis=2)
<tf.Tensor: shape=(2, 3, 12), dtype=int32, numpy=
array([[[  0,   1,   2,   3,   0,  -1,  -2,  -3,   0,   2,   4,   6],
        [  4,   5,   6,   7,  -4,  -5,  -6,  -7,   8,  10,  12,  14],
        [  8,   9,  10,  11,  -8,  -9, -10, -11,  16,  18,  20,  22]],

       [[ 12,  13,  14,  15, -12, -13, -14, -15,  24,  26,  28,  30],
        [ 16,  17,  18,  19, -16, -17, -18, -19,  32,  34,  36,  38],
        [ 20,  21,  22,  23, -20, -21, -22, -23,  40,  42,  44,  46]]],
      dtype=int32)>

(예시4) (2,3,4), (2,3,4), (2,3,4) $\to$ (3,2,3,4) # axis=0

tf.stack([a,b,c],axis=0)
<tf.Tensor: shape=(3, 2, 3, 4), dtype=int32, numpy=
array([[[[  0,   1,   2,   3],
         [  4,   5,   6,   7],
         [  8,   9,  10,  11]],

        [[ 12,  13,  14,  15],
         [ 16,  17,  18,  19],
         [ 20,  21,  22,  23]]],


       [[[  0,  -1,  -2,  -3],
         [ -4,  -5,  -6,  -7],
         [ -8,  -9, -10, -11]],

        [[-12, -13, -14, -15],
         [-16, -17, -18, -19],
         [-20, -21, -22, -23]]],


       [[[  0,   2,   4,   6],
         [  8,  10,  12,  14],
         [ 16,  18,  20,  22]],

        [[ 24,  26,  28,  30],
         [ 32,  34,  36,  38],
         [ 40,  42,  44,  46]]]], dtype=int32)>

(예시5) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,3,4) # axis=1

tf.stack([a,b,c],axis=1)
<tf.Tensor: shape=(2, 3, 3, 4), dtype=int32, numpy=
array([[[[  0,   1,   2,   3],
         [  4,   5,   6,   7],
         [  8,   9,  10,  11]],

        [[  0,  -1,  -2,  -3],
         [ -4,  -5,  -6,  -7],
         [ -8,  -9, -10, -11]],

        [[  0,   2,   4,   6],
         [  8,  10,  12,  14],
         [ 16,  18,  20,  22]]],


       [[[ 12,  13,  14,  15],
         [ 16,  17,  18,  19],
         [ 20,  21,  22,  23]],

        [[-12, -13, -14, -15],
         [-16, -17, -18, -19],
         [-20, -21, -22, -23]],

        [[ 24,  26,  28,  30],
         [ 32,  34,  36,  38],
         [ 40,  42,  44,  46]]]], dtype=int32)>

(예시6) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,3,4) # axis=2

tf.stack([a,b,c],axis=2)
<tf.Tensor: shape=(2, 3, 3, 4), dtype=int32, numpy=
array([[[[  0,   1,   2,   3],
         [  0,  -1,  -2,  -3],
         [  0,   2,   4,   6]],

        [[  4,   5,   6,   7],
         [ -4,  -5,  -6,  -7],
         [  8,  10,  12,  14]],

        [[  8,   9,  10,  11],
         [ -8,  -9, -10, -11],
         [ 16,  18,  20,  22]]],


       [[[ 12,  13,  14,  15],
         [-12, -13, -14, -15],
         [ 24,  26,  28,  30]],

        [[ 16,  17,  18,  19],
         [-16, -17, -18, -19],
         [ 32,  34,  36,  38]],

        [[ 20,  21,  22,  23],
         [-20, -21, -22, -23],
         [ 40,  42,  44,  46]]]], dtype=int32)>

(예시7) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,4,3) # axis=3

tf.stack([a,b,c],axis=3)
<tf.Tensor: shape=(2, 3, 4, 3), dtype=int32, numpy=
array([[[[  0,   0,   0],
         [  1,  -1,   2],
         [  2,  -2,   4],
         [  3,  -3,   6]],

        [[  4,  -4,   8],
         [  5,  -5,  10],
         [  6,  -6,  12],
         [  7,  -7,  14]],

        [[  8,  -8,  16],
         [  9,  -9,  18],
         [ 10, -10,  20],
         [ 11, -11,  22]]],


       [[[ 12, -12,  24],
         [ 13, -13,  26],
         [ 14, -14,  28],
         [ 15, -15,  30]],

        [[ 16, -16,  32],
         [ 17, -17,  34],
         [ 18, -18,  36],
         [ 19, -19,  38]],

        [[ 20, -20,  40],
         [ 21, -21,  42],
         [ 22, -22,  44],
         [ 23, -23,  46]]]], dtype=int32)>

- 예제: (2,3,4) (4,3,4) $\to$ (6,3,4)

a=tf.reshape(tf.constant(range(2*3*4)),(2,3,4))
b=tf.reshape(-tf.constant(range(4*3*4)),(4,3,4)) 
tf.concat([a,b],axis=0)
<tf.Tensor: shape=(6, 3, 4), dtype=int32, numpy=
array([[[  0,   1,   2,   3],
        [  4,   5,   6,   7],
        [  8,   9,  10,  11]],

       [[ 12,  13,  14,  15],
        [ 16,  17,  18,  19],
        [ 20,  21,  22,  23]],

       [[  0,  -1,  -2,  -3],
        [ -4,  -5,  -6,  -7],
        [ -8,  -9, -10, -11]],

       [[-12, -13, -14, -15],
        [-16, -17, -18, -19],
        [-20, -21, -22, -23]],

       [[-24, -25, -26, -27],
        [-28, -29, -30, -31],
        [-32, -33, -34, -35]],

       [[-36, -37, -38, -39],
        [-40, -41, -42, -43],
        [-44, -45, -46, -47]]], dtype=int32)>
tf.concat([a,b],axis=1) # 에러
---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
Input In [12], in <cell line: 1>()
----> 1 tf.concat([a,b],axis=1)

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/framework/ops.py:7107, in raise_from_not_ok_status(e, name)
   7105 def raise_from_not_ok_status(e, name):
   7106   e.message += (" name: " + name if name is not None else "")
-> 7107   raise core._status_to_exception(e) from None

InvalidArgumentError: ConcatOp : Dimensions of inputs should match: shape[0] = [2,3,4] vs. shape[1] = [4,3,4] [Op:ConcatV2] name: concat
tf.concat([a,b],axis=2) # 에러
---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
Input In [13], in <cell line: 1>()
----> 1 tf.concat([a,b],axis=2)

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/framework/ops.py:7107, in raise_from_not_ok_status(e, name)
   7105 def raise_from_not_ok_status(e, name):
   7106   e.message += (" name: " + name if name is not None else "")
-> 7107   raise core._status_to_exception(e) from None

InvalidArgumentError: ConcatOp : Dimensions of inputs should match: shape[0] = [2,3,4] vs. shape[1] = [4,3,4] [Op:ConcatV2] name: concat

tnp

- tf.constant 는 너무 쓰기 어렵다.

- 넘파이와 비교하여 생기는 불만

(불만1) .reshape 메소드 불가능 // tf.reshape() 는 가능

a=np.array([1,2,3,4]).reshape(2,2)
a
array([[1, 2],
       [3, 4]])
a=tf.constant([1,2,3,4])
tf.reshape(a,(2,2))
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
       [3, 4]], dtype=int32)>

(불만2) 암묵적형변환(=알아서 눈치껏 형변환) 불가능

np.array([1,2,3,4])+np.array([3.14,3.14,3.14,3.14])
array([4.14, 5.14, 6.14, 7.14])

(불만3) .transpose(), .T 불가능 // tf.transpose()는 가능

np.array([1,2,3,4,5,6]).reshape(2,3).T
array([[1, 4],
       [2, 5],
       [3, 6]])
tf.transpose(tf.reshape(tf.constant([1,2,3,4,5,6]), (2,3)))
<tf.Tensor: shape=(3, 2), dtype=int32, numpy=
array([[1, 4],
       [2, 5],
       [3, 6]], dtype=int32)>

(불만4) .max 불가능 // tf.reduce_max()는 가능

np.array([1,2,3,4,5,6]).reshape(2,3).T.max()
6
tf.reduce_max(tf.transpose(tf.reshape(tf.constant([1,2,3,4,5,6]), (2,3))))
<tf.Tensor: shape=(), dtype=int32, numpy=6>

(불만?) (2,2) @ (2,) 의 연산

numpy

np.array([[1.0,0.0],[0.0,1.0]]) @ np.array([77,-88])
array([ 77., -88.])
np.array([77,-88])@ np.array([[1.0,0.0],[0.0,1.0]])
array([ 77., -88.])
np.array([[1.0,0.0],[0.0,1.0]]) @ np.array([77,-88]).reshape(2,1)
array([[ 77.],
       [-88.]])
np.array([77,-88]).reshape(2,1) @ np.array([[1.0,0.0],[0.0,1.0]])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [46], in <cell line: 1>()
----> 1 np.array([77,-88]).reshape(2,1) @ np.array([[1.0,0.0],[0.0,1.0]])

ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 1)

tf

I= tf.constant([[1.0,0.0],[0.0,1.0]])
x = tf.constant([77,-88])
I@ x
---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
Input In [49], in <cell line: 1>()
----> 1 I@ x

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/framework/ops.py:7107, in raise_from_not_ok_status(e, name)
   7105 def raise_from_not_ok_status(e, name):
   7106   e.message += (" name: " + name if name is not None else "")
-> 7107   raise core._status_to_exception(e) from None

InvalidArgumentError: cannot compute MatMul as input #1(zero-based) was expected to be a float tensor but is a int32 tensor [Op:MatMul]
x @ I 
---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
Input In [50], in <cell line: 1>()
----> 1 x @ I

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/framework/ops.py:7107, in raise_from_not_ok_status(e, name)
   7105 def raise_from_not_ok_status(e, name):
   7106   e.message += (" name: " + name if name is not None else "")
-> 7107   raise core._status_to_exception(e) from None

InvalidArgumentError: cannot compute MatMul as input #1(zero-based) was expected to be a int32 tensor but is a float tensor [Op:MatMul]

... 저 이런거 하루종일 생각해낼수도 있어요

tnp 사용방법 (불만해결)

import tensorflow.experimental.numpy as tnp # 앞으로 텐서플로에서 np 대신에 tnp를 사용하면 넘파이에 익숙한 문법을 모두 쓸 수 있고 
tnp.experimental_enable_numpy_behavior()  # 생성된 tf.constant 자료형은 넘파이와 유사하게 동작한다. 

선언, 선언고급

tnp.array([1,2,3])
<tf.Tensor: shape=(3,), dtype=int64, numpy=array([1, 2, 3])>
tnp.diag([1,1])
<tf.Tensor: shape=(2, 2), dtype=int64, numpy=
array([[1, 0],
       [0, 1]])>

타입

type(tf.constant([1,2,3]))
tensorflow.python.framework.ops.EagerTensor
type(tnp.diag([1,1]))
tensorflow.python.framework.ops.EagerTensor

tf.constant로 만들고 numpy처럼 쓰기

- reshape, transpose, T

tnp.array([1,2,3,4]).reshape(2,2)
<tf.Tensor: shape=(2, 2), dtype=int64, numpy=
array([[1, 2],
       [3, 4]])>
tf.constant([1,2,3,4]).reshape(2,2)
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
       [3, 4]], dtype=int32)>
tf.constant([1,2,3,4]).reshape(2,2).T
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[1, 3],
       [2, 4]], dtype=int32)>
tf.constant([1,2,3,4]).reshape(2,2).transpose().T
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
       [3, 4]], dtype=int32)>

- max

tf.constant([1,2,3,4]).reshape(2,2).transpose().T.max()
<tf.Tensor: shape=(), dtype=int32, numpy=4>

- 알아서 형 변환

tf.constant([1,2,3]) + tf.constant([3.14,3.14,3.14])
<tf.Tensor: shape=(3,), dtype=float64, numpy=array([4.1400001, 5.1400001, 6.1400001])>

- (2,2) @ (2,) 의 연산?

tnp.diag([1,1]) @ tf.constant([77,-88])
<tf.Tensor: shape=(2,), dtype=int64, numpy=array([ 77, -88])>
tf.constant([77,-88]) @ tnp.diag([1,1]) 
<tf.Tensor: shape=(2,), dtype=int64, numpy=array([ 77, -88])>

tnp는 거의 np와 유사함 $\to$ 하지만 완전히 같은것 아니다.

a = np.array([1,2,3])
a
array([1, 2, 3])
a[0]=11
a
array([11,  2,  3])
a=tnp.array([1,2,3])
a
<tf.Tensor: shape=(3,), dtype=int64, numpy=array([1, 2, 3])>
a[0]
<tf.Tensor: shape=(), dtype=int64, numpy=1>
a[0]=11
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [84], in <cell line: 1>()
----> 1 a[0]=11

TypeError: 'tensorflow.python.framework.ops.EagerTensor' object does not support item assignment

tf.Variable

선언

- tf.Variable()로 선언

a=tf.Variable([1,2])
a
<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([1, 2], dtype=int32)>

- tf.constant() 선언후 변환

tf.Variable(tf.constant([1,2,3]))
<tf.Variable 'Variable:0' shape=(3,) dtype=int32, numpy=array([1, 2, 3], dtype=int32)>

- np 등으로 선언후 변환

tf.Variable(np.array([1,2,3]))
<tf.Variable 'Variable:0' shape=(3,) dtype=int64, numpy=array([1, 2, 3])>

타입

a=tf.Variable([1,2])
type(a)
tensorflow.python.ops.resource_variable_ops.ResourceVariable

인덱싱

a= tf.Variable([1,2,3,4])
a[:2]
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2], dtype=int32)>

연산가능

- 더하기

tf.Variable([1,2])+tf.Variable([3,4])
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([4, 6], dtype=int32)>

- 그런데 tf.Variable 끼리 연산해도 그 결과가 tf.Variable 인것은 아님. (왜 이렇게 만들었어??)

a=tf.Variable([1,2])
b=tf.Variable([3,4])
type(a),type(b)
(tensorflow.python.ops.resource_variable_ops.ResourceVariable,
 tensorflow.python.ops.resource_variable_ops.ResourceVariable)
type(a+b)
tensorflow.python.framework.ops.EagerTensor

tnp의 은총을 일부만 받음

- 알아서 형 변환

tf.Variable([1,2])+tf.Variable([3.14,3.14])
<tf.Tensor: shape=(2,), dtype=float64, numpy=array([4.1400001, 5.1400001])>

- .reshape 메소드

tf.Variable([1,2,3,4]).reshape(2,2)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [113], in <cell line: 1>()
----> 1 tf.Variable([1,2,3,4]).reshape(2,2)

AttributeError: 'ResourceVariable' object has no attribute 'reshape'

대부분의 동작은 tf.constant랑 큰 차이 없음

- tf.concat

a= tf.Variable([[1,2],[3,4]])
b= tf.Variable([[-1,-2],[-3,-4]])
tf.concat([a,b],axis=0)
<tf.Tensor: shape=(4, 2), dtype=int32, numpy=
array([[ 1,  2],
       [ 3,  4],
       [-1, -2],
       [-3, -4]], dtype=int32)>

- tf.stack

tf.stack([a,b],axis=0)
<tf.Tensor: shape=(2, 2, 2), dtype=int32, numpy=
array([[[ 1,  2],
        [ 3,  4]],

       [[-1, -2],
        [-3, -4]]], dtype=int32)>

변수값변경가능(?)

a= tf.Variable([1,2])
a
<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([1, 2], dtype=int32)>
a.assign_add([-1,-2])
<tf.Variable 'UnreadVariable' shape=(2,) dtype=int32, numpy=array([0, 0], dtype=int32)>

요약

- tf.Variable()로 만들어야 하는 뚜렷한 차이는 모르겠음.

- 애써 tf.Variable()로 만들어도 간단한연산을 하면 그 결과는 tf.constant()로 만든 오브젝트와 동일해짐.

미분

모티브

- 예제: 컴퓨터를 이용하여 $x=2$에서 $y=3x^2$의 접선의 기울기를 구해보자.

(손풀이)

$\frac{dy}{dx}=6x$ 이므로, $x=2$를 대입하면 답은 12이다.

(컴퓨터로풀이)

도함수를 구하려니까 갑자기 어려움

그런데 $x=2$에서 접선의 기울기만 계산하려고 마음먹으면 쉬움

단계1: 답만계산

x1=2 
y1=3*x1**2 
x2=2+0.000001
y2=3*x2**2 
(y2-y1)/(x2-x1)
12.000003000266702

단계2: 함수화

def f(x):
    return 3*x**2 
def d(f,x):
    return (f(x+0.000001)-f(x))/0.000001
d(f,2)
12.000003001944037

단계3: lambda

d(lambda x: x**2,3) 
6.000001000927568

- 2개의 변수로 가지는 함수를 만들어보자.

def f(x,y):
    return x**2 + 3*y 
d(f,(2,3))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [153], in <cell line: 1>()
----> 1 d(f,(2,3))

Input In [149], in d(f, x)
      1 def d(f,x):
----> 2     return (f(x+0.000001)-f(x))/0.000001

TypeError: can only concatenate tuple (not "float") to tuple

- 아쉽지만 손으로 함수를 직접 구현하여 미분을 하나하나 계산하기에는 한계가 있겠음

tf.GradientTape() 사용방법

- 예제1: $x=2$에서 $y=3x^2$의 도함수값을 구하라.

x=tf.Variable(2.0)
a=tf.constant(3.0) 
mytape=tf.GradientTape()
mytape.__enter__() # 테이프를 기록 
y=a*x**2 # y=ax^2 
mytape.__exit__(None,None,None) 
mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=12.0>

- 예제2: 조금 다른예제

x=tf.Variable(2.0)
#a=tf.constant(3.0) 

mytape=tf.GradientTape()

mytape.__enter__() # 테이프를 기록 
a=x/2*3 # a=x*(3/2)
y=a*x**2 # y=ax^2=(3/2)x^3 
mytape.__exit__(None,None,None) 

mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=18.0>

$a=\frac{3}{2}x$

$y=ax^2= \frac{3}{2}x^3$

$\frac{dy}{dx}= \frac{3}{2}3 x^2$

1.5 * 3 * 4
18.0

- 테이프의 개념 ($\star$)

(상황)

우리가 어려운 미분계산을 컴퓨터에게 부탁하는 상황임. (예를들면 $y=3x^2$) 컴퓨터에게 부탁을 하기 위해서는 연습장(=테이프)에 $y=3x^2$이라는 수식을 써서 보여줘야하는데 이때 컴퓨터에게 target이 무엇인지 그리고 무엇으로 미분하고 싶은 것인지를 명시해야함.

(1) mytape = tf.GradientTape(): 컴퓨터에게 전달할 공책가 만들어짐, 연습장의 이름을 mytape이라고 쓴다.

(2) mytape.__enter__(): mytape공책을 연다

(3) a=x/2*3; y=a*x**2: 컴퓨터에게 부탁할 수식을 쓴다.

(4) mytape.__exit__(None,None,None): mytape라는 공책을 닫는다.

(5) mytape.gradient(y,x): $y$를 $x$로 미분한다는 포스트잇을 남겨서 컴퓨터한테 전달

- 예제3: 연습장을 언제 열고 닫을지 결정하는건 중요하다.

x=tf.Variable(2.0)
a=x/2*3 # a=x*(3/2)

mytape=tf.GradientTape()

mytape.__enter__() # 테이프를 기록 
#a=x/2*3 # a=x*(3/2)
y=a*x**2 # y=ax^2=(3/2)x^3 
mytape.__exit__(None,None,None) 

mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=12.0>

- 예제4: with문과 함께 쓰는 tf.GradientTape()

x=tf.Variable(2.0)
a=x/2*3 # a=x*(3/2)

with tf.GradientTape() as mytape:
    y=a*x**2 # y=ax^2=(3/2)x^3 

mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=12.0>

(해설)

with문은 아래와 같이 동작한다.

with expression as myname:
    ### with문 시작
    blabla~!
    yadiyadi~
    ### with문 끝

(1) expression이 실행되면서 오브젝트가 하나 생성됨, 그 오브젝트를 myname이라고 받음

(2) with문이 시작되면서 myname.__enter__() 가 실행

(3) 블라블라, 야디야디 실행

(4) with문이 끝나면서 myname.__exit__() 이 실행

- 예제5: 예제2를 with문과 함께 구현

x=tf.Variable(2.0)

with tf.GradientTape() as mytape:
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 

mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=18.0>

- 예제6: persistent = True

(관찰1)

x=tf.Variable(2.0)
with tf.GradientTape() as mytape:
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
mytape.gradient(y,x) # 2번실행해서 에러를 관찰하자. 
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Input In [182], in <cell line: 1>()
----> 1 mytape.gradient(y,x)

File ~/anaconda3/envs/py310/lib/python3.10/site-packages/tensorflow/python/eager/backprop.py:1032, in GradientTape.gradient(self, target, sources, output_gradients, unconnected_gradients)
   1002 """Computes the gradient using operations recorded in context of this tape.
   1003 
   1004 Note: Unless you set `persistent=True` a GradientTape can only be used to
   (...)
   1029    called with an unknown value.
   1030 """
   1031 if self._tape is None:
-> 1032   raise RuntimeError("A non-persistent GradientTape can only be used to "
   1033                      "compute one set of gradients (or jacobians)")
   1034 if self._recording:
   1035   if not self._persistent:

RuntimeError: A non-persistent GradientTape can only be used to compute one set of gradients (or jacobians)

(관찰2)

x=tf.Variable(2.0)
with tf.GradientTape(persistent=True) as mytape:
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
mytape.gradient(y,x) # 2번실행해서 에러를 관찰하자. 
<tf.Tensor: shape=(), dtype=float32, numpy=18.0>

- 예제7: watch

(관찰1) 미분하라는게 없으면 아무것도 출력안함

x=tf.constant(2.0)
with tf.GradientTape(persistent=True) as mytape:
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
print(mytape.gradient(y,x))
None

(관찰2)

x=tf.constant(2.0)
with tf.GradientTape(persistent=True) as mytape:
    mytape.watch(x)
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=18.0>

- 예제8: 자동감시기능 off

(관찰1)

x=tf.Variable(2.0)
with tf.GradientTape(watch_accessed_variables=False) as mytape:
    #mytape.watch(x)
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
print(mytape.gradient(y,x))
None

(관찰2)

x=tf.Variable(2.0)
with tf.GradientTape(watch_accessed_variables=False) as mytape:
    mytape.watch(x)
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
print(mytape.gradient(y,x))
tf.Tensor(18.0, shape=(), dtype=float32)

(관찰3)

x=tf.Variable(2.0)
with tf.GradientTape() as mytape:
    mytape.watch(x)
    a=x/2*3 # a=x*(3/2)
    y=a*x**2 # y=ax^2=(3/2)x^3 
mytape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=18.0>

숙제

$y=x^2$에서 $x=0$에서의 접선의 기울기를 구하라. (tf.GradientTape()를 이용할것)