텐서플로우에서 사용하는 텐서라는 자료형이 있습니다.
수학에서의 행렬, 벡터를 파이썬으로 표현하고싶을 때 사용하면 유용합니다.
갑자기 행렬이야기는 왜 나온 것이고 텐서를 왜 쓰는 것인지도 알아보도록 합시다.
텐서플로우 배우면 딥러닝할 수 있는게 아닙니다.
그냥 딥러닝 수학계산을 조금 더 쉽게 도와주는 라이브러리일 뿐입니다.
근데 이걸 직접 파이썬 쌩코딩으로 짜면 매우 코드가 길고 복잡해지기 때문에
- 최종 예측값 (yhat) 계산
- w값 업데이트 (back propagation)
- learning rate 만들기
- loss function 만들기
- 레이어 만들기
이런 것들을 매우 쉽게 코드한줄로 처리할 수 있게 도와주는 라이브러리인 텐서플로우를 씁니다.
텐서플로우는 tensor 라고 부르는 기본 자료형을 활용해서 정보들을 저장합니다.
Q. 뭔정보냐고요?
딥러닝 뉴럴네트워크에 집어넣을 input 값들이나 w값들을 텐서로 저장할 수 있습니다.
텐서 = tf.constant( [1,2,3] )
print(텐서)
이런 식으로 숫자같은걸 텐서로 저장할 수 있습니다. 출력하면 "tensor입니다~" 라고 나옵니다.
Q. 뭐야 리스트랑 똑같은데여 그냥 파이썬 리스트에 저장하면 안되나요?
됩니다. 원하는 w값들을 [1,2,3] 이렇게 파이썬 리스트로 저장해두고 쓸 수도 있습니다.
근데 자료들의 dimension이라고 부르는 차원이 좀 높아지면 tensor가 다루기 편합니다.
특히 이미지같은거 처리할 땐 리스트안의 리스트안의 리스트 이런 자료들을 다루게 될 텐데
(그리고 이런 자료를 3차원 자료라고 하는데)
파이썬 리스트로만 만들면 넘나 처리하기 어려워서 그렇습니다.
Q. 그럼 뭐가좋냐고요?
텐서를 이용하시면 노드에 들어갈 값 연산할 때 코드가 매우 짧아집니다.
예를 들어봅시다.
이런 뉴럴 네트워크가 있다고 칩시다.
그럼 노드1에 들어갈 숫자는 어떻게 계산하면 될까요?
노드1 = 10*w1 + 20*w2 + 30*w3 + 40*w4
이런 식으로 코드를 짜겠죠.
이전 노드 갯수가 4개라 망정이지 100개면 어쩔겁니까. 코드가 매우 길고 더러워집니다.
근데 이전 노드의 값들과 w값들을 전부 행렬이란 것에 담아버리면 ...
(10 20 30 40) (w1 w2 w3 w4) 요렇게요.
개발자 입장에서 저걸 좀 더 쉽게 표현할 수 있습니다.
야레야레 요즘 고등학교 수학시간에 행렬안배운다는게 사실이었군요. 그냥 숫자 여러개를 한 뭉텅이로 묶어놓은게 행렬입니다. ▲ 이렇게 괄호안에 숫자 담고싶은만큼 담으세요. 가로세로 배치도 알아서 하십시오. 그럼 행렬이 됩니다. 행렬에 담으면 뭐가 좋냐면 숫자를 동시에 여러개를 더하고 뺄 경우가 있는 경우 쓰면 편리합니다. 그니까 숫자들을 병렬 연산을 많이 해야된다면 이걸 쉽게 수식으로 표현가능하기 때문에 행렬을 쓰는겁니다. 예를 들면 3 + 1 이걸 해주세요~ 라고 길게 쓰는 것 보다 ▲ 이런식으로 숫자 4개를 더해라~ 라고 쓰면 편리하잖아요. 그래서 행렬에 숫자를 담아서 씁니다. 덧셈 뺄셈 나눗셈 곱셈 등이 가능합니다.
4 + 5
2 + 3
1 + 7
행렬은 곱셈을 약간 특이하게 할 수 있습니다. 이걸 이용하면 노드1값 연산이 편리해집니다.
행렬의곱 (dot 연산) 연산 법칙이라는게 있는데 ..
x 이 기호말고 º 이런 기호로 행렬 두개를 곱해라~ 라고 써있으면
1 x 5 + 2 x 6 + 3 x 7 + 4 x 8 이런 식으로 연산해야합니다.
약간 특이하죠? 더 알아보고 싶으면 행렬 곱연산을 검색해보도록 합시다.
(참고로 행렬 곱연산을 하고 싶으면 왼쪽행렬 세로줄의 갯수와 오른쪽 행렬 가로줄의 갯수가 같아야합니다. )
암튼 그래서 아까 노드1값 연산할 때
노드1 = 10*w1 + 20*w2 + 30*w3 + 40*w4 ...
이런 식으로 코드를 짜는게 아니라 님이 행렬을 알고 있다면
행렬X = (10, 20, 30, 40)
행렬W = (w1, w2, w3, w4)
노드1 = 행렬X와 행렬W 가로세로 뒤집은걸 dot연산 해주셈
이렇게 쓸 수 있습니다. 이거나 저거나 똑같이 노드1을 계산할 수 있습니다.
(가로세로 왜 뒤집냐면 그래야 행렬 곱셈이 가능하니까요)
▲ 그림으로 표현하자면 이렇습니다.
w값들이 100개 이상으로 많아지면 행렬에 담아서 곱해버리는게 훨씬 더 코드가 짧아지겠죠?
이런 짓거리가 가능하기 때문에 뉴럴네트워크 계산할 때 텐서플로우를 쓴다는겁니다.
이거 행렬연산을 파이썬 코드로 어떻게 짜냐면..
행렬X = tf.constant( [ [10,20,30,40] ])
행렬W = tf.constant( [ [w1,w2,w3,w4] ])
행렬W뒤집은거 = tf.transpose(행렬W)
노드1 = tf.matmul( 행렬X, 행렬W뒤집은거 )
print(노드1)
텐서플로우 함수들을 이렇게 쓰시면 됩니다.
그럼 아까처럼 길게 곱셈 덧셈 하는 것보다 약간 더 코드가 짧아질 수 있습니다. (노드 갯수가 많아지면요)
암튼 w1 이라는 이상한 미지수 대신 실제 숫자같은거 암거나 집어넣어보시면 실제 노드1값 계산도 해볼 수 있겠군요.