
처음으로 머신러닝 이론을 배우고 경사하강법을 구현해봤다.
비록 이미 완성되있는 Octave 모델 샘플을 파이썬으로 바꾸는 과정이었지만, 두 언어는 확실히 다르기에 완전히 구현하는데에는 어려움이 있었다.
크리스마스 이브부터 주말까지 스케쥴이 쭉 비었기에 할 일을 찾다가 코세라에서 Octave로 구현한 간단한 경사하강법 모델을 구하게 되었다. 기본적인 문법만 배우다가 완전히 완성된 모델을 갑자기 보니 머리가 텅 비게 되었다.
하지만 Andrew Ng 교수님께서 써주신 매뉴얼을 보며 코드를 하나하나 해석하게 되었고, 거기서 매우 큰 즐거움을 느끼게 되었다.
그렇게 모델을 분석하다가 이 모델을 파이썬으로 재구현해보기로 결심했다.
이때까지 배운 이론과 선형대수학, Numpy와 Matplotlib을 처음으로 써보게 되는 프로젝트였다. 그렇게 나는 작업을 시작했다.
늦은 밤이었고 나태해지는 내 자신을 막기 위해서 트위치 스트리밍으로 생방송을 키며 작업했다. 다행히도 중간중간에 몇몇 분들이 들어와서 말을 걸어주시는 덕분에 지루함이 덜 했던 것 같다.
처음으로 한 작업은 데이터셋을 불러왔다.
Coursera에서는 데이터셋을 txt 형식으로 주었기에, 개행문자(n) 단위로 자르고 컴마(,) 로 분리되어 있는 X, y 훈련 데이터들을 각각 배열로 만들어 저장했다.
그 후 matplotlib.pyplot.scatter ( 이하 plt.scatter ) 명령어로 데이터를 시각화하니,
짠! 아름답게 데이터가 불러와졌다.
내가 배운 게 헛수고가 아니라는 것을 느낀 채 내가 해야하는 것은 Cost Function(비용 함수)를 구현하는 것이다.
이 프로젝트에서는 평균제곱오차(Mean Squared Error, MSE) 함수를 비용 함수로 사용했다. 또, 보기 편하게 하기 위해 비용함수의 함수값에 1/2 를 곱해 데이터의 범위를 조금 줄였다. (평균제곱오차는 이차함수의 형태로 정의되는데, 1/2를 곱해도 함수의 최소값은 변화가 없으니 큰 변화가 없다)
이 과정에서 행렬곱을 제대로 이해하지 못해 꽤 애를 먹었던 것 같다. 분명히 mxn 행렬과 ixj 행렬을 곱하면 mxj 행렬이 된다고 기억했는데, 알고보니 np.array() 함수를 잘못 이해해서 np.transpose (행렬 전치) 함수가 제대로 작동하지 않았기 때문이었다.
Andrew Ng 교수님이 제공해주신 pdf 가이드라인을 보며 수식을 하나하나 구현해나갔다.
그렇게 비용 함수를 구현하고, 다음은 경사하강법 알고리즘의 차례가 남았다.
이 프로젝트는 원래 크리스마스 이브 10시부터 시작해 밤을 새서라도 켠왕하자는 생각이었는데, 경사하강법을 구현하다가 너무 꼬이고 Jupyter Notebook이 터져서 머리를 비우고 잔 뒤에 크리스마스날 아침에 완성했다.
이유는 시그마를 구지 내가 for i in range로 구현했기 때문이었다. np.sum이라는 아름다운 함수가 있는 것을 나는 몰랐다…
그렇게 두 세타값을 경사하강법에 돌려서 깔끔하게 1×2 행렬로 전역 최적화 지점(Global Optimization) 에 도달시켰고, 마침내 프로젝트의 90%가 완성되었다.
다음은 세타0, 세타1의 값에 따른 비용 함수 값 배열을 만들고 이를 시각화하는 과정이었는데, 많이 익숙지 않은 matplotlib을 꾸역꾸역 써가며 Surface graph와 Contour graph를 완성시켰다.
꾸역꾸역 완성한 결과 Surface graph는 보기 좀 그렇지만… Contour graph를 통해 세타0과 세타1의 값을 최적화하는데 성공했다!
프로젝트를 하나 끝내고 나니 성취감이 어마어마했다. 내가 인공지능을 허투루 배운게 아니라, 적어도 이론은 이해했으며 이를 구현할 정도는 되었다니 자신감도 생기고 더 많은 알고리즘을 배우고 싶었다.
미적분, 선형대수학도 모르는 한 중학교 3학년생이 경사하강법 알고리즘을 구현할 정도로 이해가 쉽고 친절히 설명한 강의를 무료로 제공해주신 Andrew Ng 교수님과 Coursera 분들께 감사를 표하며, 글을 마치겠다.