텐서플로우 2이와 1의 주요 차이점, 상수 변수, 문자
제일 먼저 첫 번째 셀에서 텐서플로우 1을 설치하겠습니다
pip 명령어를 사용하는데 제일 앞에
느낌표를 넣습니다 그리고 실행 버튼을 누릅니다
설치가 끝났다면 이제 프로그램을 가져와야겠지요
다음 셀에서 그 작업을 할 겁니다
만약에 여기서 버전을 확인하고 싶다면
필요한 구문도 함께 넣어놨습니다

우리가 사용하는 버전이 텐서플로우 1.13.1라고 나오네요
텐서플로우 1에서 빠르게 복습해 볼 부분은
상수와 변수인데, 텐서플로우 2.0과 큰 차이가 있기 때문입니다
바로 상수와 변수 값을 구하는 방법입니다
그 부분을 바로 살펴보죠

먼저, 변수 값의 정의입니다
텐서플로우에서 가져온 constant 함수를 사용하면 됩니다
텐서플로우 라이브러리에 저장한 단축어 tf를 사용하고요
constant 함수에는 텐서를 넣게 되는데
일반적으로 텐서플로우에서 생성한 상수나 변수가 텐서입니다
왜냐하면 텐서플로우를 쓰는 목적 자체가
고급 텐서를 사용해 다양한 기능과 툴을 이용하고
인공 신경망이나 딥 Q 네트워크 등 고급 딥러닝이나 AI 모델링을
구축하기 위함이죠
따라서 텐서플로우 상수나 변수를 생성할 땐
일반적으로 텐서가 됩니다
그래서 제가 여기 tf.constant에 tensor라고 이름을 붙였죠
constant 함수 안에 입력할 것은
텐서의 형태와 값입니다
대괄호가 두 개이므로 2열 2행의 2차원 텐서입니다
tf. constant를 정의한 다음 불러와 보면
값은 나오지 않고 형태만 확인할 수 있습니다
보시다시피 2x2 텐서고 입력값의 유형만이
출력되는데 여기서는 정수입니다
바로 여기서 텐서플로우 1과 2이 차이를 보이게 됩니다
만약 텐서 값을 가져오고자 한다면
이 경우 23, 4, 23, 51이죠
eval이라는 함수를 사용할 수 있습니다
eval은 tensor로 이름 붙인 tf.constant에서 불러올 수 있습니다
하지만 텐서 값을 가져오기 위해 eval 함수를 불러오려면
텐서플로우 1에서는 텐서플로우 세션을 먼저 시작해야 합니다
상수의 값에 접근하고자 할 때는
변수의 값에 접근할 때도 마찬가지로
세션을 먼저 초기화해야 합니다
지금 우리는 아직 세션을 초기화하지 않았죠
따라서, eval 함수를 불러와서
텐서 값을 가져오려고 하면 ValueError 메시지가 뜹니다
아래에는 왜 에러가 떴는지 설명도 포함되어 있습니다
No default session is registered 라고 나오죠?
그러니 세션을 먼저 등록해야 합니다
세션을 초기화한 후에 세션에 들어갈 모든 변수를 초기화해야
변수나 상수의 값에 접근할 수 있습니다
그렇다면 다음 섹션에서는 세션을 초기화해
상수의 값을 가져와 보도록 하겠습니다

여기 다음 섹션을 보시면 기존에 정의했던 상수의 값을
가져오기 위해, 제일 먼저 세션을 초기화할 겁니다
새로운 변수를 먼저 정의할 텐데요 session이라고 이름 붙였고
텐서플로우의 클래스 중 하나인 session 클래스인 인스턴스로 생성 됩니다
이렇게 세션을 초기화할 수 있습니다
그리고 말씀드렸듯이 세션에 들어갈 모든 변수도 초기화해야 합니다
run 함수를 사용해서 tf.global_variables_initializer를 입력합니다
세션에서 저장할 모든 전역 변수를 초기화하는 겁니다
초기화된 세션을 한 번 더 run 함수를 사용해 텐서에 연결하고
이때 나올 새로운 변수가 텐서 내의 값이므로 tensor_value로 이름 붙입니다
그러면 이번에는 상수 텐서 내의 값을 불러올 수 있죠
세션을 등록해뒀기 때문에 상수 텐서 값에 접근할 수 있습니다
좋습니다 지금까지 설명한 내용이
텐서플로우 2.0와 다르기 때문에 간단히 살펴보았습니다
텐서플로우 2.0에서는 상수와 변수의 값을
가져오는 방법이 훨씬 더 간단해졌습니다
이번에는 텐서플로우 1에서의 변수를 간단히 살펴보도록 하죠

텐서플로우 변수를 정의할 때는
아까와 달리 함수를 사용하지 않습니다
텐서플로우 라이브러리에서 불러온 Variable이라는 클래스를 사용합니다
따라서 변수는 Variable 클래스의 인스턴스가 됩니다
하지만 이때도 입력 내용은 같습니다
텐서의 형태와 함께 값을 입력하면 됩니다
마찬가지로 텐서플로우 변수를 정의할 때도 보통 텐서를 사용하므로
저도 예시에서 텐서 변수를 만들어 보았습니다
여기서도 똑같이 다른 조치 없이 변수를 불러오면
2x2의 텐서 형태와 값이 정수라는 것만 알 수 있습니다
하지만 값은 출력하지 못하죠 마찬가지로
세션이 초기화하지 않았다면 변수 값을 불러올 수 없습니다
변수 텐서의 eval 함수를 호출해 변수의 값에 접근하려고 하면
등록된 세션이 없기 때문에 ValueError 메시지가 뜹니다
자 그럼, 변수의 값을 불러오기 위해서
이번에도 먼저 세션을 초기화해야 합니다

session 오브젝트를 텐서플로우의 session 클래스 인스턴스로 생성합니다
그 다음 run 함수를 이용해 세션의 모든 변수를 초기화합니다
tf.global_variables_initializer를 쓰면 되겠죠
변수에서는 곧바로 eval 함수를 호출할 수 있습니다
변수의 경우 상수와는 달리 그 자체로 오브젝트가 되기 때문에
variable 클래스의 인스턴스로서 바로 eval 함수를 사용해
변수 값을 가져올 수 있습니다 물론 먼저 세션을 등록해야 합니다
따라서 윗부분에서 eval 함수를 불러온 것과는 달리
여기에서는 세션을 입력해야 합니다
위에서는 세션이 없어서 ValueError가 나왔지만 이제 세션을 등록했기 때문에
보시다시피 이를 eval 함수로 입력하면
값이 나오네요
이제부터는 텐서플로우 2.0을 본격적으로 공부해 보겠습니다
같은 작업을 텐서플로우 2.0에서는 다른 방식으로 수행해 볼 텐데요
훨씬 간단한 방법으로 텐서의 값을 가져와 볼 겁니다
물론 텐서플로우 2.0의 명령어를 실행하기 전에
먼저 설치를 해야겠지요
저번처럼 pip 명령어를 사용하고 앞에 느낌표를 입력해줍니다
텐서플로우 2.0.0 버전과 GPU가 설치되어 더 빠른 실행이 가능합니다
명령어를 실행시키면 이런 결과물이 나옵니다
텐서플로우에서 설치해야 하는 의존성도
이렇게 다운로드 됩니다
하나의 패키지로 설치가 되는 거죠
그리고 나서 가져오기를 할 텐데
여기서 넘파이도 가져와 줍니다 값을 불러오는 과정에서 넘파이도
사용하기 때문입니다
2.0 버전에 넘파이 기반 기능이 추가되었다고 보시면 되는데
앞으로 함께 살펴보겠습니다
텐서플로우 버전을 확인하고 싶다면 이렇게 입력하면 됩니다
텐서플로우 2.0.0을 사용하고 있죠
이 구성에서 먼저 상수를 공부해보도록 하겠습니다
자, 상수를 어떻게 정의할까요?
텐서플로우 1에서 했던 방식과 동일합니다
텐서플로우 라이브러리에서 constant 함수를 가져오고
그 안에 텐서 형태를 입력해줍니다
여기 2행 2열의 값이 포함된 텐서가 있습니다
2.0 버전을 사용하고 있으니 '텐서플로우 20'이라 이름 붙이겠습니다
그리고 이걸 불러오면
값을 바로 가져올 수 있습니다
아주 간단하지 않나요?
이전에는 tf.Tensor 안에 id와 2행 2열이라는 형태,
그리고 값의 유형만 알 수 있었는데
이제는 배열에서 2행 2열에 해당하는 값도 출력됩니다
처음에 입력한 것과 같은 값이죠
이게 바로 새로운 주요 특성입니다 사용하기가 훨씬 수월해졌죠
텐서플로우 2.0에 도입된 큰 변화이기도 합니다
만약에 텐서의 형태만 몇 차원인지 알고 싶다면
상수 텐서에서 shape 속성만 불러올 수 있습니다
그럼 텐서 형태만 출력됩니다
2행 2열이죠
그 다음으로는 상수 값을 가져오는 또 다른 방법을 알아보겠습니다
이 방법을 사용하면 값만 불러오게 되고 위의 정보는 나타나지 않습니다
여기 배열만 출력이 되었죠 어떤 방법을 썼냐면
여기 보시다시피 넘파이를 이용해 텐서의 상수 값을 바로 가져온 겁니다
이게 넘파이를 가져온 이유죠
세션을 사용할 필요 없이 이렇게 상수 텐서를 입력한 뒤
넘파이와 괄호를 넣어주면 값을 바로 가져올 수 있습니다
매우 실용적인 방법으로
대부분의 경우에 세션이 필요하지 않게 되었습니다
텐서플로우 1을 사용할 땐 매번 새로 세션을
열어야 했는데 번거로운 과정이 생략된 겁니다
텐서플로우 프로그램을 만들거나 특히 신경망이나
신경 기계 학습을 새로 만들 때도
매번 세션을 열어야 했는데
이제는 그럴 필요가 없습니다
지금까지가 텐서플로우 기본 기능에서 2.0 버전에 새로 생긴 변화였습니다
하지만 신경망 구축에서도 달라진 점을 또 발견할 수 있습니다
그리고 앞으로 세션을 사용하는 일이 있는지도 지켜보도록 하겠습니다
자, 그리고 마찬가지로 넘파이 배열을
텐서플로우 형태로 되돌릴 수도 있습니다
자세한 설명을 위해 numpy_tensor라는 넘파이 어레이를 하나 만들었습니다
넘파이 어레이를 함수를 쓰는데
numpy의 약어인 np로 입력하고 array 함수를 불러옵니다
마찬가지로 대괄호가 2개인 형태로 되어있어서
2행 2열에, 안에는 값이 포함되어 있습니다
아까와 똑같죠? 넘파이 어레이를 사용할 뿐입니다
그리고 이 넘파이 어레이를
텐서플로우 텐서로 바꾸기 위해서는 라이브러리에서 tf를 불러오고
constant 함수를 취해서
numpy_tensor를 안에 입력하면 됩니다
이 constant 함수를 사용할 때는 대괄호를 이용해
값을 입력할 수도 있지만 넘파이 어레이를 직접 넣어도
넘파이에서 생성되었을 뿐 똑같은 텐서플로우 텐서를 나타냅니다
이걸 불러오면, 아까처럼 기본 정보가 먼저 나옵니다
텐서라는 점이 명시되고 id 식별자, 2행 2열이라는
텐서의 형태, 텐서 값의 유형이 정수라는 것과
배열과 모든 값이 나옵니다
자, 이제 텐서플로우 상수를 다루는 게 훨씬 쉬워졌네요
텐서플로우 2.0의 새로운 특징 중 하나였습니다
그럼 변수로 넘어가 볼까요?
먼저 변수를 어떻게 정의하는지 살펴볼 텐데요
사실 이전과 동일합니다
라이브러리에서 tf를 가져와서 variable 클래스로 지정하죠
그 안에 대괄호 2개와 값을 입력합니다
그리고 값을 불러오고 싶을 때 두 가지 방법을 사용할 수 있습니다
tf2_variable을 불러오면 이전과 달리 해당 정보만 불러올 뿐 아니라
배열과 값도 출력됩니다
텐서의 변수 값을 불러오는 두 번째 방법은
아까와 똑같습니다
생성해둔 텐서 변수 tf2_variable를 가져와서
텐서플로우 2.0에 연동된 numpy 함수를 호출하면
곧바로 값이 출력되는데 이번에는
배열과 유형만 나옵니다
훨씬 간단하지요
지금부터는 여러분이 사용할 수 있는 툴을 하나 더 소개하려고 합니다
상수는 값을 바꿀 수 없기 때문에 변수에만 사용할 수 있습니다
변수의 특정값을 바꾸는 것인데요
예를 들어, 여기 있는 1행 3열의 셀 값을
바꾸고 싶다고 해봅시다
그럼 변수를 가져와서 1행에 해당하는 인덱스 0을 입력하고
3열에 해당하는 인덱스 2를 입력합니다
그리고 .assign(100)을 입력하면 됩니다
assign은 variable 클래스에서 사용할 수 있는 함수로
변수 내에 어떤 값이든 바꾸고자 할 때 사용합니다
그런 다음 이 명령어를 실행시키면
텐서에 대한 새로운 정보가 다음과 같이 나타나고
값을 확인할 수 있는데, 실제로 1행 3열에
3이었던 값이 100으로 바뀐 걸 확인할 수 있습니다
알아두면 좋을 내용이지만
다 외우려고 할 필요는 없습니다
강의에서 노트북이 제공되기 때문에 컴퓨터에 보관해서
프로젝트를 수행할 때마다 가까이 두고 있으면
텐서플로우 2.0의 유용한 함수들을 간편하게 찾아볼 수 있습니다
그럼 돌아와서 tf2_variable을 다시 불러오면
이때도 같은 결과물이 나오겠죠
assign 함수는 tf2_variable에서 원하는 셀만 변경한 것이기 때문에
새로 뭔가 생성된 게 아닙니다
앞서 생성했던 tf_variable의 값을 변경했을 뿐입니다
이제 상수와 변수를 다룸에 있어
텐서를 만들 때는 수정하지 않을 constant 함수를 사용해
상수 텐서를 만들 수 있습니다
아니면 텐서플로우 변수를 만들어서
나중에 수정할 수도 있죠
지금은 나중에 할 연산을 고려해 수정하지 않겠습니다
그래서 보시는 것처럼 셀이 2개 행과 2개 열로 배치된
간단한 2D 텐서를 만들었습니다
이 텐서로 텐서플로우 2.0의 다양한 연산을 보여드리겠습니다
먼저 스칼라와 텐서 간의 간단한 덧셈입니다
보시는 것처럼 여기 텐서가 있죠
텐서의 셀 [1, 2], [3, 4]에 일괄적으로 2를 더해줄 겁니다
네 개의 셀 각각에 2를 가진
새로운 2D 텐서를 만들 필요가 없습니다
그냥 2를 더하면 텐서플로우 2.0이 알아서
텐서 안의 값에 각각 2를 더합니다
이렇게 실제로 해보면 결과가 출력되죠
텐서에 2를 더하니 [3, 4], [5, 6]이 나왔네요
정말 간단한 연산입니다
다음은 스칼라와 텐서의 곱셈입니다
덧셈과 다를 게 없습니다
텐서를 선택하고 원하는 스칼라와 곱하면 됩니다
이 경우에는 5가 되겠죠 2D 텐서랑 곱하지 않아도 됩니다
나중에 보게 될 내용이지만
이 노트북에서 두 텐서 사이의 행렬곱을 다룰 예정이며
그때는 두 개의 텐서를 서로 곱하게 됩니다
하지만 지금 스칼라와 텐서 곱셈은 스칼라만 추가하면 결과가 나옵니다
[5, 10], [15, 20]이네요
정말 간단하지만 꼭 알고 계셔야 합니다
이제 텐서플로우 텐서에 사용이 가능한
넘파이 함수 연산에 대해서도 알아보도록 하겠습니다
이런 넘파이 함수의 예를 들자면 제곱이 있습니다
텐서에 있는 각 요소의 제곱값을 구하는 겁니다
이번에는 여기부터 시작해 보죠
텐서플로우 텐서 객체에 있는 모든 숫자의 제곱값을 구하겠습니다
이때 넘파이의 제곱 함수에는
셀의 제곱을 구하고 싶은 텐서만 입력합니다
그러면 다음과 같은 셀로 구성된 새로운 텐서가 출력됩니다
1의 제곱인 1 2의 제곱인 4
3의 제곱인 9 4의 제곱인 16이 나옵니다
역시 간단하죠
텐서플로우 텐서에 넘파이 함수를 직접 사용할 수 있으며
텐서플로우만으로 모든 걸 다 할 필요는 없습니다
제곱근으로 다른 예시를 보여드리죠
이번에는 텐서플로우 텐서 객체에 있는
모든 숫자의 제곱근을 계산합니다
앞서 배운 것과 완전히 같은 방식입니다
다만 이번에는 넘파이의 SQRT 함수를 사용해
텐서에 있는 모든 셀의 제곱근을 구하겠습니다
그러면 이렇게 1의 제곱근이 출력됩니다
2의 제곱근도 나왔죠
3의 제곱근은 물론이고 4의 제곱근인 2도 나왔습니다
이제 이해하셨겠죠
지수나 로그 같은 다른 함수도 원한다면 사용이 가능합니다
하지만 어떤 함수를 사용해도 우리가 사용하는 넘파이 함수에
텐서플로우 텐서를 적용한다는 점은 동일합니다
이제 다음으로 가죠
앞서 말했듯이 두 텐서 사이의 행렬곱을 구할 수 있습니다
하지만 주의하세요
텐서에 텐서 20을 곱하는 게 아닙니다
텐서 20은 이전에 실제로 만든 텐서라는 점을 기억하세요
어떤 텐서였는지 다시 확인해 보죠
텐서 20입니다
여기 있군요 [23, 4], [32, 51]
이제 새로운 텐서 [1, 2], [3, 4]와 텐서 20의
행렬곱을 구할 겁니다
그러면 결과가 [87, 106], [197, 216]
이렇게 출력됩니다
이런 결과가 나오게 된 계산 과정은 무엇일까요
그건 행렬 곱셈입니다
87을 예시로 살펴보죠
[1, 2], [3, 4]가 있습니다
그리고 텐서플로우 20은 [23, 4], [32, 51]입니다
왼쪽 위에 있는 첫 번째 셀의 행렬 곱셈은
(1×23)+(2×32)'입니다
2×32는 64고 64+23은 87이죠
첫 번째 셀의 값은 이렇게 계산되었습니다
정확하게 87이죠
이게 행렬 곱셈입니다
한번 더 확인해 볼까요
이것과 저것의 행렬 곱셈을 살펴보겠습니다
왼쪽 위는 (3×5)+(4×15)입니다
오른쪽 위는 (3×10)+(4×20)이죠
왼쪽 아래는 (5×5)+(6×15)
오른쪽 아래는 (5×10)+(6×20)입니다
가장 기초적인 행렬 곱셈입니다
이걸 보여드린 목적은 선형대수학 복습이 아니라
넘파이의 행렬곱 함수로 두 텐서 플로우 텐서의
행렬 곱셈을 계산하는 과정을 보여드리기 위해서였습니다
텐서플로우를 사용하면 상수 함수를 통해
문자열 상수도 만들 수 있습니다
그러니까 상수 함수로 불러낸
텐서플로우 라이브러리를 사용하면
이전처럼 텐서 입력이 아닌 문자열 입력이 가능합니다
그러니까 문자열과 연결되는 변수로 미리 지정한
tf_string 변수를 호출하면
형태를 비롯한 텐서플로우 객체의
다양한 정보를 얻을 수 있습니다
형태는 지금은 값이 없네요
형식은 당연히 문자열입니다
문자열 안에 있는 실제 값은 텐서플로우입니다
이것이 문자열 텐서플로우입니다
텐서플로우로 문자열을 정의하는 방법이었습니다
꼭 텐서플로우로 해야 하는 건 아니지만
심화 자연어 처리와 같은 작업을 위해
텐서플로우로 문자열을 만들 수 있으면 좋습니다
문자열을 정의했다면 이제 간단한 문자열 연산을 해보겠습니다
처음에 할 연산은 길이 측정으로 자연어 처리에서 널리 쓰입니다
문자열의 길이, 즉 글자 수를 측정하려면
다음과 같은 특정한 방법을 사용해야 합니다
먼저 텐서플로우 라이브러리에 있는 문자열 모듈에서
length 함수를 호출합니다
물론 텐서플로우 문자열 객체는 tf_string입니다.
호출이 완료되면 이번에도 숫자만 출력되고 형태 값은 없습니다
그리고 tensorflow의 글자 수대로 10이라는 값이 출력됩니다
정말 간단한 문자열이었습니다 이제는 조금 복잡한 걸 해보죠
그래도 여전히 간단합니다
문자열을 다른 형식으로 해독하는 디코딩 연산입니다
여기서는 UTF8을 사용하겠습니다
별로 쓸 일은 없겠지만 나중에 고급 자연어 처리를 한다면
무언가를 디코딩할 일이 생길 수도 있습니다
텐서플로우 라이브러리의 문자열 모듈 옆에 있는
unicode_decode 함수를 사용합니다
unicode_decode 함수에는 두 가지 요소가 필요합니다
첫 번째는 문자열이고 두 번째는 그 문자열을 변환할 형식입니다
문자열을 UTF8로 디코딩하면 문자열에 있는 글자마다 개수를 세므로
이번에는 형태의 값이 숫자로 출력됩니다
UTF8 형식으로 디코딩해서
정수 형태인 10이라는 숫자가 출력된 것입니다
역시 간단한 문자열 연산이었습니다
텐서플로우로 심화, 또는 간단한 자연어 처리를 한다면
유용할 한 가지가 더 있습니다
그리고 텐서플로우를 사용한다면 텐서플로우 신경망을 구축하고
사용하면서 심화 자연어 처리를 하게 될 수 있죠
바로 문자열 배열을 저장하는 방법입니다
문자열 여러 개를 만들었는데 이것들을 배열한다고 생각해 보세요
이 방법을 사용하려면 또 다시 텐서플로우 상수 함수를 사용합니다
이번에는 다양한 문자열을 포함한 한 쌍의 대괄호를 사용한
1D 배열을 만들겠습니다
첫 번째 문자열은 TensorFlow입니다
두 번째는 Deep learning 세 번째는 AI입니다
이렇게 만들어진 간단한 배열은 변수로 사용되지만 실제로는
상수로 기능하는데, 저는 tf_string_array라고 부릅니다
문자열 배열이 완성되었다면
이제는 이 배열을 반복해야 합니다
배열에 포함된 다양한 요소를 계속 반복해야
다양한 문자열을 하나씩 개별적으로 쓸 수 있습니다
심화 자연어 처리에서 자주 쓰는 방법이죠
이걸 하려면 간단한 for 루프를 쓰면 됩니다
저는 여기에 for 루프를 썼습니다
문자열 배열에 포함된 다양한 문자열을 반복해야 합니다
문자열 배열이 반복되고 구성요소가 잘 호출됨을 확인하기 위해
다양한 문자열을 프린트했습니다
첫 번째는 TensorFlow 두 번째는 Deep learning
그리고 세 번째는 AI입니다
여기까지 덤으로 알려드렸습니다
텐서플로우 2.0으로 심화 자연어 처리를 한다면 유용할 것입니다