(3주차) 3월21일
import tensorflow as tf
import numpy as np
tf.config.experimental.list_physical_devices('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.concat([a,b,c],axis=0)
(예시2) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,9,4)
tf.concat([a,b,c],axis=1)
(예시3) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,12)
tf.concat([a,b,c],axis=2)
(예시4) (2,3,4), (2,3,4), (2,3,4) $\to$ (3,2,3,4) # axis=0
tf.stack([a,b,c],axis=0)
(예시5) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,3,4) # axis=1
tf.stack([a,b,c],axis=1)
(예시6) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,3,4) # axis=2
tf.stack([a,b,c],axis=2)
(예시7) (2,3,4), (2,3,4), (2,3,4) $\to$ (2,3,4,3) # axis=3
tf.stack([a,b,c],axis=3)
- 예제: (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.concat([a,b],axis=1) # 에러
tf.concat([a,b],axis=2) # 에러
- tf.constant 는 너무 쓰기 어렵다.
- 넘파이와 비교하여 생기는 불만
(불만1) .reshape 메소드 불가능 // tf.reshape() 는 가능
a=np.array([1,2,3,4]).reshape(2,2)
a
a=tf.constant([1,2,3,4])
tf.reshape(a,(2,2))
(불만2) 암묵적형변환(=알아서 눈치껏 형변환) 불가능
np.array([1,2,3,4])+np.array([3.14,3.14,3.14,3.14])
(불만3) .transpose(), .T 불가능 // tf.transpose()는 가능
np.array([1,2,3,4,5,6]).reshape(2,3).T
tf.transpose(tf.reshape(tf.constant([1,2,3,4,5,6]), (2,3)))
(불만4) .max 불가능 // tf.reduce_max()는 가능
np.array([1,2,3,4,5,6]).reshape(2,3).T.max()
tf.reduce_max(tf.transpose(tf.reshape(tf.constant([1,2,3,4,5,6]), (2,3))))
(불만?) (2,2) @ (2,) 의 연산
numpy
np.array([[1.0,0.0],[0.0,1.0]]) @ np.array([77,-88])
np.array([77,-88])@ np.array([[1.0,0.0],[0.0,1.0]])
np.array([[1.0,0.0],[0.0,1.0]]) @ np.array([77,-88]).reshape(2,1)
np.array([77,-88]).reshape(2,1) @ np.array([[1.0,0.0],[0.0,1.0]])
tf
I= tf.constant([[1.0,0.0],[0.0,1.0]])
x = tf.constant([77,-88])
I@ x
x @ I
... 저 이런거 하루종일 생각해낼수도 있어요
import tensorflow.experimental.numpy as tnp # 앞으로 텐서플로에서 np 대신에 tnp를 사용하면 넘파이에 익숙한 문법을 모두 쓸 수 있고
tnp.experimental_enable_numpy_behavior() # 생성된 tf.constant 자료형은 넘파이와 유사하게 동작한다.
tnp.array([1,2,3])
tnp.diag([1,1])
type(tf.constant([1,2,3]))
type(tnp.diag([1,1]))
- reshape, transpose, T
tnp.array([1,2,3,4]).reshape(2,2)
tf.constant([1,2,3,4]).reshape(2,2)
tf.constant([1,2,3,4]).reshape(2,2).T
tf.constant([1,2,3,4]).reshape(2,2).transpose().T
- max
tf.constant([1,2,3,4]).reshape(2,2).transpose().T.max()
- 알아서 형 변환
tf.constant([1,2,3]) + tf.constant([3.14,3.14,3.14])
- (2,2) @ (2,) 의 연산?
tnp.diag([1,1]) @ tf.constant([77,-88])
tf.constant([77,-88]) @ tnp.diag([1,1])
a = np.array([1,2,3])
a
a[0]=11
a
a=tnp.array([1,2,3])
a
a[0]
a[0]=11
- tf.Variable()로 선언
a=tf.Variable([1,2])
a
- tf.constant() 선언후 변환
tf.Variable(tf.constant([1,2,3]))
- np 등으로 선언후 변환
tf.Variable(np.array([1,2,3]))
a=tf.Variable([1,2])
type(a)
a= tf.Variable([1,2,3,4])
a[:2]
- 더하기
tf.Variable([1,2])+tf.Variable([3,4])
- 그런데 tf.Variable 끼리 연산해도 그 결과가 tf.Variable 인것은 아님. (왜 이렇게 만들었어??)
a=tf.Variable([1,2])
b=tf.Variable([3,4])
type(a),type(b)
type(a+b)
- 알아서 형 변환
tf.Variable([1,2])+tf.Variable([3.14,3.14])
- .reshape 메소드
tf.Variable([1,2,3,4]).reshape(2,2)
- tf.concat
a= tf.Variable([[1,2],[3,4]])
b= tf.Variable([[-1,-2],[-3,-4]])
tf.concat([a,b],axis=0)
- tf.stack
tf.stack([a,b],axis=0)
a= tf.Variable([1,2])
a
a.assign_add([-1,-2])
- 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)
단계2: 함수화
def f(x):
return 3*x**2
def d(f,x):
return (f(x+0.000001)-f(x))/0.000001
d(f,2)
단계3: lambda
d(lambda x: x**2,3)
- 2개의 변수로 가지는 함수를 만들어보자.
def f(x,y):
return x**2 + 3*y
d(f,(2,3))
- 아쉽지만 손으로 함수를 직접 구현하여 미분을 하나하나 계산하기에는 한계가 있겠음
- 예제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)
- 예제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)
$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
- 테이프의 개념 ($\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)
- 예제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)
(해설)
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)
- 예제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번실행해서 에러를 관찰하자.
(관찰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번실행해서 에러를 관찰하자.
- 예제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))
(관찰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)
- 예제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))
(관찰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))
(관찰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)
$y=x^2$에서 $x=0$에서의 접선의 기울기를 구하라. (tf.GradientTape()를 이용할것)