레이블이 파이썬인 게시물을 표시합니다. 모든 게시물 표시
레이블이 파이썬인 게시물을 표시합니다. 모든 게시물 표시

파이썬에서 부울이 아닌 값에 대한 논리연산자

C먼저 확인해보면

C언어에서는 bool 타입이 따로 존재하지 않는다. 0이면 false, 그렇지 않으면 true이다. 심지어는 float도 피연산자로 참여할 수 있다. 그래도 어쨌든 논리연산자의 결과값은 0 아니면 1이 되는 1byte 정수형을 리턴한다.

예를 들어

int a = 10;

float b = 3.14;

printf("%d, %d\n", a && b, sizeof(a && b));

위의 코드에서 출력은 1, 1 이다.


파이썬의 and, or

그런데 파이썬은 조금 더 변태같다.

a = 10

b = 20

print(a and b, a or b)

결과는 20, 10이다. 어째써? and와 or는 다음과 같이 구현되어 있다.

a and b => if a is true, return b, else return a
a or b => if a is true, return a, else return b

and의 경우 a가 참이면 b를 리턴한다. 결과적으로 a and b가 참인지 거짓인지는 b에 달린 상황이다. 만약 a가 거짓이면 그냥 a를 리턴한다. a가 거짓인 줄 알고 리턴하니까 a and b도 거짓이 된다. 이 때 b는 체크하지 않는다.

or의 경우 a 가 참이면 그냥 a를 리턴한다. a가 참이니까 a or b 도 참이다. 이 때 b는 체크하지 않는다. 만약 a가 거짓이면 b를 리턴한다. a or b가 참인지 거짓인지는 b에 달렸다.

한 번 더 정리하자면 a and b 에서 a 가 거짓이면 b를 체크하지 않고 a를 리턴한다. a or b에서 a 가 참이면 b를 체크하지 않고 a를 리턴한다. a and b에서 a가 참이면 b를 리턴하고, a or b에서는 a가 거짓이면 b를 리턴한다.


C언어의 논리연산자는 정수형 입력을 받아서 정수형 출력을 한다. 파이썬의 논리연산자는 입력 타입이 정해져 있지 않다. 그래서 입력 타입이 부울이 아닌 경우 엉뚱한 결과가 발생한다.


bool이 아닌 값들의 참, 거짓

뭐 당연하겠지만 또 웃기는 것은 True의 타입은 <class 'bool'>인데 산술연산에 참여할 때는 정수 1처럼 여겨진다는 것이다.

print(True + True)

결과는 2이다.


또 한 가지 팁이라면 파이썬에서는 None을 거짓으로 취급한다. 반대로 리스트나 기타 오브젝트는 참으로 취급한다. 아래 예제에서

a = [1, 2, 3]

print(a or None)

print(None and True)

결과는 [1, 2, 3], 그리고 None이다.


그런데 비어있는 리스트, 문자열, 딕셔너리, 셋, 튜플 따위는 거짓으로 취급한다.

print( [] or dict() or set() or tuple() or '' or 10 )

결과는 10이다. 10 앞에 나열한 모든 것들은 전부 거짓으로 취급된다.



bool로 변환해야 True가 된다

여기 또 다른 함정이 있다. 예를 들어 10은 bool로 형변환하면 True가 되긴 하지만 그렇다고 1이 True인 것은 아니다.

a = 10

print(a is True)

print(a == True)

결과는 둘 다 False이다. a는 정수 10일 뿐, bool도 아니고 True도 아니다. 


if문을 쓰지 않고 a가 참인지 체크하려면 간단히 bool로 형변환해보면 된다.

print(bool(a))

결과는 당연히 True이다.


마지막으로 아래 식을 확인해보자.

print(type(a and True))

print(type(True and a))

결과는 <class 'bool'>, <class 'int'> 이다. and 연산의 리턴 타입을 보면서 파이썬의 함수는 리턴 타입이 정해져있지 않다는 사실이 새삼 현실로 다가온다.


and, or 응용하기

파이썬의 이러한 특성을 이용하면 변태같은 코딩이 가능하다.


if a < b : func() #이 문장은

a < b and func() #요렇게 바꿀 수 있다.


if not (a < b) : func()

a < b or func()


조건문 대신 and와 or를 쓸 수 있다. 영 and와 or가 어색하다면 and 대신 then, or 대신 otherwise로 읽어보면 조금 더 자연스럽다. 어셈블리어를 해봤으면 매우 자연스러울 수 있다, 점프처럼 생각하면 되니까.

여기에 보태서 None이 거짓으로 인식되는 점을 이용해 None 체크를 할 수 있다.


if a is not None: b = a

else: b = somethingDefault #이 두 문장은

b = a or somethingDefault #요 한 문장으로 바꿀 수 있다.


a를 b에 대입하는데 만약 None이면 미리 정해준 기본값을 대입하도록 한 것이다. 같은 원리로 비어있는 리스트를 체크할 수도 있다.


myList = []

x = min(myList or [-1])

x = min(myList) #에러 발생


만약 myList == [] 즉 비어있는 리스트라면 에러가 발생한다. 이걸 try 로 잡아서 어쩌구 해도 되지만 어차피 비어있을 경우 x에 기본값 -1을 넣을 작정이라면 위와 같이 or를 이용할 수 있다.


결론

당연히 논리연산자의 피연산자는 bool로 묵시적 형변환이 일어나는 줄 알았고, 당연히 출력은 무조건 bool인줄 알았는데 입력 타입을 그대로 살려서 출력한다니 좀 어이없긴 하다. 파이썬의 철학이 단 하나의 목적을 위한 단 하나의 아름다운 코드 아닌가? 이런 변태같은 부분은 파이썬의 기본 철학을 정면으로 부정하는 것이다. 통일성과 간편함을 동시에 추구하는 것이 그렇게 쉬운 일은 아닌 셈이다.

파이썬의 이런 점이 마음에 들지 않는다, 혹은 헷갈려서 공부 못하겠다 싶으면 정수나 기타 이상한 타입은 일절 논리 연산에 참여시키지 말아야 한다. 반드시 bool(a) 또는 a != 0 과 같은 코드를 써서 명시적으로 bool로 변환해주는 것이 좋다. C를 제외한 대부분의 언어, 그러니까 Java와 C#에서는 당연히 이렇게 한다. 논리연산에는 bool만 참여할 수 있기 때문에 반드시 명시적 형변환이 필요하다. 차라리 이게 나은 것 같은데.

Read More

Visual Studio 2017 + 파이썬 + Tensor Flow 셋팅

Windows에서 파이썬이 돌아간다는 사실은 모두가 알면서도 막상 딥러닝 프레임워크를 돌릴 때는 리눅스를 사용하게 된다. 프레임워크를 사용한 수많은 예제들이 모두 리눅스 기반으로 돌아가기도 하거니와 왠지 윈도우 파이썬은 뭔가 호환이 안 될것 같은 기분 탓이다. 요즘은 파이참(PyCharm)이라는 좋은 개발 환경도 있고, Visual Studio에서도 파이썬을 기본으로 서포트해주기 때문에, 윈도우에서도 특별한 고생 없이, 어쩌면 리눅스보다 더 편하게 파이썬을 사용할 수 있다.

그러나 시작은 언제나 두려운 법. 파이썬 초보들도 쉽게 Tensor Flow를 셋팅할 수 있도록 튜토리얼을 작성해본다.

우선 Visual Studio를 깔아야한다. 2017버전을 설치할 때, Python 개발 환경을 체크해야 한다. 혹시 설치할 때, 체크하는 것을 놓쳤다면 나중에라도 Visual Studio Installer를 실행해서 추가 설치가 가능하다.


여기서 파이썬을 선택한 뒤 수정 버튼을 누른다.

설치를 진행하면 VS의 파이썬 코딩 툴 뿐 아니라 파이썬 자체가 새로 설치된다. 이미 기존에 파이썬이 설치되어 있더라도 마찬가지이다. 여기서 의문이 드는 점은 여러 개의 파이썬을 설치할 경우 어떻게 되느냐 이다. 파이썬은 다양한 버전이 존재하고, 사람마다, 소스마다 써야 하는 버전이 다르기 때문에 자연스럽게 여러 가지 버전을 모두 설치하게 된다. Visual Studio 역시 이러한 파이썬의 사정을 잘 알고 있기 때문에, 설치된 파이썬 버전을 직접 관리할 수 있도록 기능이 제공된다.

개별 파이썬 버전은 폴더 단위로 관리된다. 설치 폴더 밑에 python.exe가 있고, 하위 폴더로 Scripts, Lib 등이 있다.


여러 개의 파이썬이 설치될 때는 위와 같은 폴더가 여러 개 생성된다.

이제 VS에서 파이썬 프로젝트를 만들어보자.

파이썬 프로젝트를 선택하면 된다.




솔루션 탐색기에서 Python 환경을 보면 Python 3.6 (64-bit) 라고 되어 있고 바로 뒤에 (전역 기본값) 이라고 되어 있다. 새 프로젝트를 만들고 나서 특별히 환경을 지정하지 않았으므로 기본값이 지정된 것이다. 특별히 다른 파이썬 버전으로 현재 프로젝트를 구동하고 싶다면 환경에서 오른쪽을 눌러서 고를 수 있다.

이쯤에서 소개할 것은 아나콘다이다. 아나콘다는 파이썬 배포판 중 하나라고 할 수 있다. 예를 들어 리눅스가 래드햇, 페도라 등 다양한 배포판을 가지고 있는 것과 같다. 리눅스 배포판이 핵심 커널 뿐 아니라 다양한 유틸리티를 포함하고 있는 것처럼 아나콘다도 자주 쓰는 라이브러리를 미리 탑재하고 있다.

파이썬 환경에서 중요한 포인트 중 하나는 각각의 파이썬 환경마다 다른 라이브러리를 설치할 수 있다는 것이다. 파이썬에서 설치한 라이브러리는 Lib 폴더에 저장된다.

파이썬에서는 라이프러리를 패키지 단위로 관리한다. 패키지란 라이브러리 묶음으로 생각하면 될 것이다. 예를 들어 우리가 OpenCV를 설치할 때, 각각의 lib파일을 개별적으로 다운받는 것이 아니라 OpenCV라는 묶음으로 설치한다. 이렇듯 패키지란 개념은 이미 일상에서 자연스럽게 사용하고 있다. 파이썬에서는 패키지 다운로드를 위한 툴을 기본적으로 탑재하고 있는데, 그것이 바로 pip이다. pip로 다운받은 패키지는 파이썬 폴더/Lib/site-packages 폴더에 저장된다.

Visual Studio를 사용하면 pip를 좀 더 쉽게 사용할 수 있다. 메뉴에서 [도구]->[Python]->[Python 환경]으로 들어가면 조그만한 도킹 창이 뜬다. 맨 위에서 원하는 환경을 선택한다. 아나콘다를 설치했거나, 기타 다른 버전의 파이썬을 설치했다면 해당 환경을 고를 수 있다. 만약 설치한 환경이 보이지 않는다면 수동으로 추가해야 한다.

 가운데 콤보박스에서 패키지(PyPI)를 고른다.



설치된 패키지가 나타나는데, 특별히 다른 것을 설치하지 않았다면 달랑 pip, setuptools 정도 보일 것이다. X표를 누르면 패키지를 지울 수 있고 화살표를 누르면 최신 버전으로 업데이트한다.

패키지 검색 창에 tensorflow라고 입력해보자. 엄청나게 많은 항목이 뜨는데 대부분의 것들은 텐서플로우를 보조하는 툴이거나 실험 버전 등이고 중요한 것은 그냥 'tensorflow', 그리고 'tensorflow-gpu' 이다. 'tensorflow-gpu'는 말 그대로 GPU 버전이고 그냥 tensorflow는 CPU only 버전이다. 둘 다 설치하면 어떻게 될까? 조금 꼬이긴 하는데 마지막에 설치된 버전이 적용된다. Keras를 사용하면 내부적으로 tensorflow를 참조하는데, 여기서도 마지막에 설치된 버전을 참조한다.





일단 CPU 버전인 'tensorflow'를 설치해보자. 클릭 한 번이면 설치가 시작되고, 설치 과정은 [출력] 창에 표시되는데, 이게 아무래도 좀 불친절하다. 프로그래스 바, 혹은 진행중 표시가 없으니 설치가 되는 건지 됐다는 건지 안 됐다는 건지 알 수가 없다. 하여튼 설치됨 메시지가 뜨면 완료된 것이다.


설치 과정을 잘 읽어보면 알겠지만 필요한 라이브러리들은 자동으로 설치된다. 만약 설치가 안 된다면 pip 버전을 업데이트 한 후 다시 설치해보자.



설치가 끝났으면 이제 헬로 텐서플로우를 외쳐볼 시간이다. 솔루션에서 .py 파일을 하나 선택한 뒤 다음과 같이 입력한다.

import tensorflow as tf

hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))

참고로 솔루션에서 진하게 표시된 파일이 F5를 누를 때 처음 시작될 파일이다. 파이썬은 Matlab과 마찬가지로 메인함수가 없고 아무 파일이나 골라서 먼저 실행할 수 있다.

2018-04-27 08:34:58.484009: I T:\src\github\tensorflow\tensorflow\core\platform\cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
b'Hello, TensorFlow!'
Press any key to continue . . .

위와 같이 메시지가 뜨면 성공이다. 맨 윗 줄에 Your CPU supports 어쩌구 하는 경고 메시지는 무시해도 된다. 원래 Tensorflow를 최적화하려면 CPU에 맞게 다시 빌드해야 하는데, 현재는 범용으로 컴파일된 라이브러리를 쓰고 있기 때문에 나타나는 메시지이다.

여기까지 진행되면 CPU 버전 텐서플로우 설치가 완료된 것이다. 이제 tensorflow-gpu를 설치해보자. GPU버전은 사용하려면 CUDA를 지원하는 NVidia 그래픽 카드가 있어야 하고, CUDA, cudnn 설치도 해야 하서 좀 복잡하고 귀찮지만 CPU버전에 비해 거의 20배 빠르기 때문에 충분히 해볼만한 가치가 있다. 사실 GPU가 아니면 딥러닝은 시작되지도 못했다.

Tensorflow 버전에 따라서 요구하는 CUDA, cudnn 버전이 다르다. 확실히 하려면 Tensorflow 홈페이지를 방문해서 확인해보면 된다. 영 귀찮으면 그냥 최신 버전을 설치하면 그냥 저냥 잘 될테지?? 라고 생각하면 오산이다. 텐서플로우 버전에 정확히 맞는 것을 찾아서 설치해야 한다. 현재 tensorflow 1.7 버전은 CUDA 9.0, cudnn 7.1.x 에서 동작한다.


우선 CUDA를 설치해야 하는데, 구글에서 cuda를 검색하면 자연스럽게 다운로드 페이지로 이동한다. 자신의 OS를 잘 선택하고 windows버전을 골라서 다운로드한다. 설치 과정은.. 그냥 next만 누르면 알아서 잘 설치된다. 설치 도중에 화면이 깜빡거릴 수 있으며 단순히 다음을 눌러서 간편 설치를 할 경우 그래픽 드라이버도 새로 설치된다.

다음은 cudnn을 설치해야 하는데, 우선 다운로드 하려면 NVidia ID로 로그인을 해야 한다. ID가 없으면 새로 만들고 로그인한다.



로그인 후 버전을 선택한다. 자신의 CUDA 버전에 맞는 것으로 잘 골라서 다운로드 하면 된다.

CUDA는 설치 프로그램이 알아서 설치를 했지만 cndnn은 받아보면 그냥 압축 파일이다. 아무곳이나 편리한 곳에 풀어놓은 뒤, 설치경로/cuda/bin 폴더를 PATH로 잡아줘야 한다.

혹시 PATH 잡는 법을 모르는 사람들을 위해 안내까지 만들었다~ 시작메뉴에서 제어판을 검색해서 실행한 뒤 아래처럼 폴더 경로를 넣는다. 캡쳐하기 귀찮아서 한꺼번에 모아서 캡쳐 ㅎㅎ




변경된 환경변수를 적용하기 위해서는 재로그인/혹은 재부팅을 해야 한다.

이제 Python pip에서 tensorflow-gpu를 다운로드하고 실행해보면 된다. 다운로드하는데 20분이 걸릴 수도 있으니 천천히 기다려보자.


2018-04-27 23:38:33.037407: I T:\src\github\tensorflow\tensorflow\core\platform\cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
2018-04-27 23:38:33.783060: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:1344] Found device 0 with properties:
name: GeForce GTX 965M major: 5 minor: 2 memoryClockRate(GHz): 1.15
pciBusID: 0000:01:00.0
totalMemory: 2.00GiB freeMemory: 1.64GiB
2018-04-27 23:38:33.789763: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:1423] Adding visible gpu devices: 0
2018-04-27 23:38:34.209099: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:911] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-04-27 23:38:34.213833: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:917]      0
2018-04-27 23:38:34.216125: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:930] 0:   N
2018-04-27 23:38:34.218824: I T:\src\github\tensorflow\tensorflow\core\common_runtime\gpu\gpu_device.cc:1041] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 1405 MB memory) -> physical GPU (device: 0, name: GeForce GTX 965M, pci bus id: 0000:01:00.0, compute capability: 5.2)
b'Hello, TensorFlow!'
Press any key to continue . . .

위와 같이 나오면 성공 ^^

Read More
Powered by Blogger.