Introduction to Computation and Programming Using Python 3rd Edition 번역 완료!

MIT 존 구탁(John Guttag) 교수의 “Introduction to Computation and Programming Using Python 3rd Edition” 책 번역을 드디어 완료했습니다. 이 책은 단순히 파이썬 문법만 다루지 않고 계산적 사고를 돕기 위해 파이썬으로 여러가지 흥미로운 알고리즘을 구현해 보고 머신러닝을 포함해 파이썬 과학 생태계의 여러 측면을 배울 수 있습니다. 다음은 각 장의 내용을 요약한 것입니다.

1장은 계산적 사고와 두 종류의 지식에 대해 설명하는 것으로 시작됩니다. 프로그램 고정식 컴퓨터와 프로그램 내장식 컴퓨터의 차이점을 언급하면서 간단한 프로그래밍 발전 역사를 엿봅니다. 끝으로 프로그래밍 언어의 기본 구조, 문법, 정적 시맨틱, 시맨틱에 대해 설명하면서 어떻게 좋은 프로그램을 만들 수 있는지, 다른 언어와 파이썬 간의 차이점은 무엇인지를 소개하는 것으로 마칩니다.

2장은 파이썬의 기본 요소를 소개합니다. 먼저 간단한 파이썬의 특징과 역사를 살펴보고 아나콘다와 스파이더 IDE를 설치하는 방법을 설명합니다. 그다음 파이썬의 객체와 기본 스칼라 타입에 대해 알아 보고 몇 가지 예를 셸 프롬프트로 실행해 봅니다. 이어서 변수에 대해 설명하고 변수에 객체를 재할당할 때 생기는 미묘한 문제를 설명합니다. 그다음 if 문을 사용한 분기 프로그래밍을 설명합니다. 이와 함께 파이썬 코드를 여러 줄로 나누어 작성하는 방법도 소개합니다. 다음으로 문자열과 인덱싱, 슬라이싱, f-문자열을 설명합니다. 파이썬에서 사용자에게 입력을 받는 방법을 설명하면서 유니코드 인코딩에 대한 소개도 하고 있습니다. 그다음은 반복문입니다. while 문과 for 루프를 사용해 반복이 필요한 문제를 처리하는 방법을 소개합니다. 자연스럽게 range 함수도 소개합니다. 마지막으로 2~1000 사이의 소수의 합을 출력하는 퀴즈로 마무리합니다.

3장은 2장에서 배운 if, for, while 문을 사용해 간단한 프로그램을 작성하는 방법을 배웁니다. 먼저 완전 열거(exhaustive enumeration) 방식으로 제곱근을 구합니다. 이 방식의 단점을 생각해 본 다음 이분 검색(bisection search)으로 제곱근의 근삿값을 찾는 프로그램을 작성합니다. 부동소수점 숫자가 컴퓨터에서 어떻게 표현되는지 알아 보고 float 타입의 변수를 비교 연산자에 사용했을 때 발생할 수 있는 문제를 생각해 봅니다. 이 과정에서 비트, 이진수, 유효 숫자, 정밀도 등에 대해 알게 됩니다. 마지막으로 보편적인 근사 알고리즘인 뉴턴 방법을 사용해 다항식의 근을 찾는 코드를 작성합니다.

4장은 코드의 재사용성을 높이기 위해 함수의 필요성을 언급하고 함수를 정의하고 사용하는 방법을 소개합니다. 3장에서 만들었던 제곱근을 구하는 코드를 함수로 다시 구현해 봅니다. 그다음 위치 인수와 키워드 인수, 가변 길이 인수에 대해 소개합니다. 종종 혼동이 되는 변수의 유효범위에 대해 자세히 설명합니다. 이를 위해 스택 프레임을 설명하고 예를 들어 스택의 생성 소멸 과정을 자세히 안내합니다. 그다음 함수의 사양(specification)에 대해 소개합니다. 특히 추상화를 대해 재미있는 비유로 설명합니다. 지금까지 만든 함수에 독스트링으로 사양을 작성해 봅니다. 그다음 하나의 함수를 여러 개로 쪼개어 보고 함수를 인수나 반환값으로 사용하는 방법을 배웁니다. 이 과정에서 람다 함수를 소개합니다. 마지막으로 객체의 메서드에 간단히 소개하고 마칩니다.

5장은 튜플, 리스트, 레인지, 딕셔너리를 소개합니다. 튜플과 문자열의 비슷한 점과 다른 점을 소개하고 함수 반환 값에 많이 사용하는 복수 할당을 알아 봅니다. 레인지와 반복 가능한 객체에 대해 알아 보고 range 함수를 for 문에 적용해 봅니다. 그다음은 부수 효과로 골치 아플 수 있지만 유용한 객체인 리스트입니다. 이 절에서 리스트 안의 객체와 변수 사이의 바인딩에 대해 조금 더 자세히 알아 봅니다. 이 과정에서 id 함수와 is 연산자를 배웁니다. 또한 매개변수 디폴트 값에 빈 리스트를 넣었을 때 발생할 수 있는 놀라운 일도 살펴 봅니다. 리스트를 복제하기 위해 슬라이싱하는 방법과 copy 모듈을 사용하는 방법을 배웁니다. copy.deepcopy가 생각만큼 deep하지 않다는 사실도 알 수 있습니다. 그다음 파이썬 프로그래머들이 즐겨 사용하는 리스트 내포를 소개합니다. 하지만 두 개 이상 중첩하면 골치 아픕니다. 마지막으로 리스트를 사용해 고차 함수(high-order function)을 구현해보고 내장 고차 함수인 map의 사용법을 배웁니다. 5장은 여기서 끝나지 않고 집합(set)에 대해 소개하고 딕셔너리로 넘어갑니다. 딕셔너리에서 자주 사용되는 메서드를 소개하고 딕셔너리 내포도 다룹니다. 마지막으로 딕셔너리를 사용해 책 암호(book cipher)를 구현하는 간단한 예제로 마무리합니다!

6장은 재귀와 전역변수를 다룹니다. 먼저 재귀 예제의 헬로 월드인 팩토리얼을 반복문을 사용해 만든 것과 재귀를 사용해 만든 것을 비교하여 봅니다. 그다음 피보나치 수열을 재귀를 사용해 만들어 봅니다(사실 피보나치 수열은 피보나치가 만든 것이 아니군요!). 재귀를 사용하지 않고 더 효율적으로 피보나치 수열을 만들 수도 있습니다(이건 번역서 깃허브에 담겨 있습니다). 숫자가 아닌 문제에도 재귀를 사용할 수 있습니다. 예를 들면 팰린드롬(palindrome)이죠. 팰린드롬을 구현하면서 분할 정복에 대해 살짝 소개합니다. 이에 대해서는 12장에서 다시 알아 봅니다. 마지막으로 전역 변수는 일반적으로 사용하지 않도록 권장하지만 꼭 필요한 경우가 있기 때문에 간략히 소개합니다.

7장은 모듈과 파일입니다. 파이썬의 모듈 개념에 대해 소개하고 표준 라이브러리에 들어 있는 math와 calendar를 사용한 예제를 다룹니다. 점 표기법을 사용해 모듈 안에 있는 함수나 상수를 사용하는 법을 익히는 것이 주 목적입니다. 예제로는 미국의 추수감사절의 날짜를 계산하고 크리스마스 전까지 기간을 계산합니다. 덕분에 미국의 추수감사절이 항상 네번째 목요일이 아니었다는 사실과 제 생일이 둠스데이였다는 것도 알게 되었네요! 마지막으로 파이썬에서 간단한 텍스트 파일을 쓰고 읽는 방법을 알아 봅니다. 여기에서 with 문을 사용할 때 장점도 알 수 있습니다.

8장은 테스트와 디버깅을 설명합니다. 화이트 박스 테스트와 블랙 박스 테스트를 예를 들어 설명하고 테스트 수행시 참고할 사항을 안내합니다. 버그에 대한 역사적 기원을 짧게 훑어 보고 어떤 종류의 버그가 가장 지독한지 종류에 따라 고찰해 봅니다. 디버깅은 배울 수 있는 기술입니다. 이 장은 전문적인 디버거를 사용하지 않습니다. 대신 실제 버그가 있는 코드를 사용해 버그를 찾아 해결하는 과정을 단계적으로 자세히 안내합니다. 마지막으로 프로그램에 문제가 생겼을 때 생각해볼 몇 가지 실용적인 팁을 안내합니다.

9장은 예외를 소개합니다. 파이썬에서 예외는 예외적이지 않습니다. 🙂 try-except 문장을 소개하고 예상되는 예외를 어떻게 캐치할 수 있는지 설명합니다. 반대로 예외를 사용하지 않았을 때 번거로움에 대해서도 비교해서 언급합니다. 마지막으로 assert 문을 소개하면서 장을 마칩니다.

10장은 클래스에 대한 내용입니다. 먼저 추상 데이터 타입과 클래스에 대한 개념을 소개하고 클래스, 타입, 객체, 속성을 설명합니다. 매직 메서드 __init__를 사용해 객체를 초기화해 보고, 클래스 변수와 인스턴스 변수의 차이점을 배웁니다. 이어서 __str__ 메서드와 다양한 매직 메서드를 알아 봅니다. 특히 중위 연산자를 위한 매직 메서드를 사용해 해싱 가능한 객체를 만드는 방법을 소개합니다. 클래스 상속과 다형성을 설명하기 위해 학생을 위한 클래스를 설계합니다. 이 과정에서 수퍼클래스, 서브클래스, 오버라이딩 등을 배울 수 있고 중위 연산자를 위한 매직 메서드의 호출 우선순위도 알 수 있습니다. 다단계 상속을 만드는 이유와 유용성을 예를 들어 설명하고 캡슐화와 정보 은닉을 위해 성적 클래스도 만듭니다. 인스턴스 변수를 효율적으로 참조하기 위한 제너레이터 사용법도 여기서 배웁니다. 마지막으로 여러 종류의 주택 모기지를 위한 클래스를 만들어 보면서 상속과 오버라이딩을 연습합니다. 과연 어떤 모기지를 대출받아야 이득일까요?

11장은 알고리즘 복잡도에 대해 소개합니다. 계산 복잡도에 대해 기초 개념부터 차근차근 설명하기 때문에 쉽게 이해할 수 있습니다. 간단한 코드의 복잡도를 추정해 보면서 복잡도의 경우 덧셈항과 곱셈 상수에 큰 의미가 없다는 것을 이해합니다. 시간 복잡도를 중점으로 다루지만 공간 복잡도에 대해서도 조금 소개합니다. 점근 표기법으로 대문자 O 표기법과 대문자 Θ 표기법의 차이점을 소개합니다. 그다음 대표적인 복잡도(상수, 로그, 선형, 로그 선형, 다항, 지수)를 코드 예제와 함께 소개합니다. 마지막으로 그래프를 사용해 복잡도를 비교합니다. 다항 복잡도도 피하는게 좋지만 지수 복잡도에 비하면 껌이죠! 🙂

12장은 11장에서 배운 계산 복잡도를 바탕으로 몇 가지 알고리즘을 분석해 봅니다. 파이썬 리스트에서 원소를 참조할 때 복잡도를 고찰해 봅니다. 이 과정에서 파이썬 리스트의 구현 방식을 알 수 있습니다. 다음으로 리스트의 원소가 정렬되어 있다고 가정할 때 이진 검색을 사용해 원소를 찾는 함수를 작성하고 복잡도를 추정합니다. 그럼 정렬하는데는 얼마나 시간일 걸릴까요? 대표적인 정렬 알고리즘으로 선택 정렬, 합병 정렬을 구현하고 복잡도를 추정합니다. 그다음 파이썬에 있는 팀소트 알고리즘을 소개하고 sort 메서드와 sorted 함수를 사용해 봅니다. 마지막으로 해시 테이블을 사용해 딕셔너리 룩업을 상수 시간에 처리하는 방법을 배웁니다.

13장에서는 맷플롯립으로 그래프를 그리는 방법을 배웁니다. 간단한 선 그래프를 그리는 예제로 시작해서 그래프를 저장하거나 제목이나 축 레이블을 넣는 방법을 소개합니다. 또 선 그래프의 마커와 색 등을 바꾸는 방법과 rcParams을 통해 기본 설정을 지정하는 방법을 소개합니다. 그다음 10장에서 만든 모기지 클래스를 활용하여 여러 종류의 모기지 비용을 그래프로 그려 비교합니다. 마지막으로 코로나 바이러스 같은 전염병이 거리두기 제한에 따라 어떻게 확산되는지 시뮬레이션하는 인터랙티브한 그래프를 그립니다. 이를 통해 맷플롯립의 위젯을 사용하는 방법을 배울 수 있습니다.

14장은 최적화에 대해 다룹니다. 이 장에서 소개하는 두 문제는 배낭 문제와 그래프 문제입니다. 먼저 간단한 배낭 문제를 탐욕 알고리즘으로 해결해 보면서 장단점과 복잡도에 대해 고찰합니다. 그다음 완전 열거 방식으로 배낭 문제의 최적해를 찾아 봅니다. 그리고 왜 이런 방식이 오랜 시간이 걸리는지 생각해 봅니다. 그다음 유명한 오일러의 쾨니히스베르크 다리 문제를 소개하면서 그래프 문제를 설명합니다. 간단한 그래프의 최단 경로를 찾기 위해 유향 그래프 클래스를 직접 만들어 깊이 우선 탐색과 너비 우선 탐색을 실행하고 두 방식의 차이점을 짚어 봅니다.

15장은 동적 계획법에 대해 설명합니다. 리처드 벨먼이 왜 이 기법의 이름을 ‘동적 계획법’으로 지었는지에 대한 일화를 소개하면서 시작합니다. 6장에서 재귀 방식으로 만들었던 피보나치 수열 함수를 동적 계획법의 상향식 방법과 하향식 방법으로 해결하는 과정을 소개합니다. 그다음 14장의 배낭 문제를 이진 결정 트리를 사용해 최적의 해를 찾는 과정을 설명합니다. 이 방식의 단점을 보이고 더 빠르게 해결하기 위해 동적 계획법을 적용해 봅니다. 마지막으로 분할 정복과 동적 계획법의 차이점에 대해 안내하면서 마칩니다.

16장은 랜덤 워크 시뮬레이션을 구현합니다. 매 타임 스텝마다 무작위로 걷는 (술 취한) 사람이 있다면 시간이 갈수록 원래 위치에서 멀어질까요? 아니면 원래 자리로 돌아올까요? 그다음은 동이나 서쪽으로만 움직이는 사람과, 남쪽으로는 두 걸음씩 가는 사람을 시뮬레이션합니다. 편향된 랜덤 워크 시뮬레이션이죠. 이 과정에서 시뮬레이션에 대해 배우고 수집한 데이터를 시각화하여 의미있는 통찰을 이끌어 내는 과정을 익힙니다.

17장은 확률과 분포를 다루는 긴 장입니다. 간단한 주사위 확률을 계산하는 것으로 시작합니다. 그다음 동전 던지기로 큰 수의 법칙에 대해 설명을 이어갑니다. 동전의 앞면과 뒷면이 나올 확률을 모른다고 가정하고 실험을 통해 수집한 데이터로 확률을 추정하는 추론 통계를 설명합니다. 이어서 여러 가지 분포에 대해 소개하고 직접 데이터로 만들어봅니다. 정규 분포, 균등 분포, 이항 분포, 지수 분포, 벤포드 분포 등입니다. 짬짬이 신뢰 구간과 이항 계수 등도 곁들여 있습니다. 마지막으로 해싱 충돌의 확률을 시뮬레이션으로 추정하고 메이저리그의 월드 시리즈에서 우승하려면 정말 운이 따라 주지 않아도 되는지 알아봅니다.

18장은 몬테 카를로 시뮬레이션을 다룹니다. 이름의 유래를 알아보는 이야기로 시작해서 주사위 게임이 확률 연구에 얼마나 지대한 공헌(?)을 했는지 들려줍니다. 파스칼의 친구가 물어 본 주사위 게임의 확률을 수학적으로 계산해 보고 시뮬레이션으로도 확인합니다. 그다음 카지노에 있는 크랩스 게임을 시뮬레이션하여 어느 곳에 돈을 거는 것이 좋은지 알아 봅니다. 마지막으로 𝜋 값을 찾기 위한 역사적 흔적을 들려주고 확률적인 방법으로 𝜋 값을 찾는 뷔퐁-라플라스 방법을 소개합니다. 그리고 직접 시뮬레이션해 봅니다. 18장을 읽고 나면 카지노에는 가지 않는 편이 좋다고 생각할 것 같네요.

19장은 드디어 그 유명한 중심극한정리를 다룹니다. 보스톤 마라톤 대회 데이터를 사용해 샘플링한 표본의 평균이 어떻게 정규 분포를 형성하는지 그래프를 만들어 확인해 봅니다. 시뮬레이션을 통해 표본의 크기가 커짐에 따라 신뢰 구간이 점점 향상되는 것을 배웁니다. 그다음 표본의 표준 오차 공식을 제시하고 실제로 하나의 표본에서 만든 표준 오차가 표본 평균의 표준 편차와 거의 비슷한지 확인해 봅니다. 마지막으로 표본 오차를 사용해 표본 평균의 신뢰 구간을 계산하는 방법을 보입니다.

20장은 실험 데이터로부터 간단한 선형 회귀 모델을 만드는 방법을 배웁니다. 먼저 스프링의 변위를 측정한 데이터로 선형 회귀와 다항 회귀를 만듭니다. 하지만 아직 사이킷런을 사용하는 것은 아니고 넘파이의 polyfit 함수를 사용합니다. 자연스럽게 최소 제곱이나 목적 함수에 대해 소개하며 한 발 더 나아가 고차 다항식일 때 발생하는 과대적합에 대해서도 설명합니다. 이어서 어떤 발사체의 궤적을 따라 측정한 높이를 사용해 선형 모델을 만들고 최소 제곱 대신 결정 계수를 사용해 모델을 평가하는 방법을 안내합니다. 마지막으로 지수적으로 분포된 데이터는 y 축을 스케일링하여 선형 모델을 훈련할 수 있다는 것을 소개합니다.

21장은 앞의 장들을 기반으로 가설 검정에 대해 본격적으로 파헤칩니다. 먼저 가설 검정을 만든 피셔의 우유가 섞인 차 테스트 이야기로 시작해서 가상의 신약의 효과에 대한 유의성을 확인하기 위해 필요한 도구를 설명합니다. 영 가설, 대립 가설, 유의 수준 t-점수, 자유도 등이죠. 이 과정에서 t 분포를 만든 고셋의 재미있는 뒷 이야기도 들을 수 있습니다. 신약의 가설 검정 결과는 효과가 없다는 영가설을 기각할만하네요. 하지만 안심하기는 이릅니다. p-값을 주의해야 하는 이유를 아주 자세히 설명하고 있습니다. 그다음 단측 2표본 검정과 1표본 검정을 설명합니다. 물론 이 장에서 사용하는 검정 도구는 사이파이입니다. 이어서 간단한 검정 예를 두 개 더 들고 다중 가설일 경우 본페로니 교정을 취해야 하는 이유를 설명합니다. 그다음은 베이즈 정리입니다. 조건부 확률을 사용해 랜덤하게 선택한 한 미국 남성이 미국의 평균 몸무게보다 많을 확률을 계산하고, 베이즈 정리를 사용해 유방조영상의 결과가 양성인 한 여성이 진짜 암일 확률을 계산해 봅니다. 이를 통해 유방조영상이 정말 필요한지 의문을 가질 수 있겠네요.

22장은 통계를 잘못 사용한 역사와 방법(!)을 간략히 소개합니다. 데이터 오염, 오해하기 좋은 시각화, 상관관계와 인과관계의 혼동, 앤스컴 콰르텟, 샘플링 편향, 체리 피킹, 외삽 문제, 백분율 기준 문제, 회귀 오류 등입니다. 어휴 정말 과거 사례를 돌이켜 보면 부끄럽기 짝이 없군요! 통계를 이렇게 사용해서는 안되겠죠!

23장은 판다스를 소개합니다. 2판에는 없었는데 3판에서 새롭게 추가되었습니다. 판다스 데이터프레임과 시리즈 객체의 구조를 설명하고 파이썬으로 데이터프레임을 만들고 열을 추가하거나 삭제하는 방법을 소개합니다. 그다음 loc와 iloc 메서드를 사용해 행과 열을 선택하는 방법을 배웁니다. 그리고 groupby 메서드와 불리언 인덱싱도 간략히 다룹니다. 미국 도시의 기온 데이터와 화석 연료 소비량 데이터를 판다스로 읽은 후 두 데이터의 상관관계를 파악해 보면서 다양한 판다스 기능을 연습합니다.

24장부터는 머신러닝을 다룹니다. 이 장은 이어지는 장에서 실제 모델을 만들기 전에 특성 벡터와 거리 지표에 대해서 소개합니다. 특성 공학, 특성 선택에 대해서도 소개합니다. 그리고 간단한 동물 데이터를 사용해 파충류와 다른 동물을 구분하는 규칙을 찾아봅니다. 이 에에서부터 거리 지표의 필요성을 언급하고 민코프스키 거리를 소개합니다. 그다음 유클리드 거리를 사용해 각 동물 사이의 거리를 측정하고 어떤 문제점이 있는지 파악해 봅니다.

25장은 비지도 학습 방법의 하나인 군집을 소개합니다. 군집 결과를 비교하는 측정 방법을 소개하고 K-평균 군집을 직접 수행하기 위한 파이썬 클래스를 작성합니다. 그다음 가상의 데이터를 생성해서 K-평균 군집을 수행해 봅니다. 그다음 간단한 동물데이터를 사용해서 식습관에 따라 동물을 클러스터링해 봅니다. 이 과정에서 z-스케일링과 최소-최대 스케일링에 대해서도 배웁니다.

26장은 분류에 대해서 다룹니다. 회귀와 마찬가지로 과대적합에 대해서 소개하면서 오차 행렬을 사용하는 방법과 클래스 불균형에 대해서도 언급합니다. 또한 정확도 외에 다양한 분류 지표를 설명합니다. 보스턴 마라톤 데이터를 사용해서 선수의 성별을 예측하는 예제를 만듭니다. k-최근접 이웃을 사용해서 마라톤 선수의 성별을 예측해 보고 n-겹 교차 검증에 대해서도 소개합니다. 다음은 로지스틱 회귀를 사용하여 같은 문제를 풉니다. 로지스틱 회귀 모델의 가중치를 이해하는 방법을 설명합니다. 훈련된 모델을 사용해 ROC 곡선을 그려보고 AUC도 계산합니다. 마지막으로 타이타닉 데이터를 사용해서 생존자를 예측하는 로지스틱 회귀 모델을 만들어 봅니다. 이를 통해 난파 사고에서 살아 남으려면 돈이 많고, 젊고, 여성이어야 한다는 것을 알 수 있습니다!

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.