반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍8 - Open API를 이용해 주식 차트 그리기




이번에는 인터넷에 공개된 API를 이용해 주식 정보를 받아오고 이에 대한 차트를 Matplotlib으로 그려보도록 하겠습니다. 불행히도 주식 정보를 API로 제공하는 국내 사이트는 없습니다.


증권사에서 자체적인 API를 제공해주고 있긴 한데, 그냥 가져다 쓰기에는 무척이나 번거로운 작업이고 절차도 까다롭습니다. 하지만 걱정은 여기까지~


우리나라 주가 정보를 편리하게 제공해주는 사이트가 하나 있는데, 바로 미국의 야후입니다.

주가 정보를 제공하는 주소는 다음과 같습니다.


http://chartapi.finance.yahoo.com/instrument/1.0/{종목코드}/chartdata:type=quote;range=10y/csv

 

예를 들어 삼성전자의 종목코드는 005930입니다. 야후는 전세계 주식 정보를 제공해주고 있어서 이 종목코드가 어느 나라의 것인지 구분하기 위해 종목코드 뒤에 식별자를 부여해줘야 하는데, 우리나라는 KS가 식별자입니다. 따라서 005930.KS가 유효한 삼성전자 종목코드가 됩니다.


인터넷 브라우저를 열고 아래의 주소를 입력한 후 엔터를 쳐보세요~


http://chartapi.finance.yahoo.com/instrument/1.0/005930.KS/chartdata;type=quote;range=10y/csv


그러면 아래와 같이 브라우저에 삼성전자에 대한 주가 정보가 텍스트로 나타납니다.



브라우저에 나타난 데이터에서 우리가 관심이 있는 것은 주가입니다. 바로 요부분입니다.

20060717,594000.0000,598000.0000,576000.0000,584000.0000,224900
....
....

이 부분은 모두 콤마로 6개 부분으로 구분되어 있습니다. 
순서대로 날짜, 종가, 고가, 저가, 시작가, 거래량입니다.

우리는 이 데이터를 받아와서 Matplotlib으로 주식 차트를 그려볼 겁니다. 일반적인 주식 차트는 그날의 종가를 기준으로 그려줍니다. 자 그러면 아래의 코드를 보시죠~

stockreader.py

stockreader.py의 주요 부분만 살펴보겠습니다.

>>> bytesdate2num(fmt, encoding='utf-8')
이 함수는 8자리로 된 날짜 데이터를 Matplotlib이 인식하는 숫자로 변경합니다. 

이제 실제로 주식 차트를 그려주는 아래의 코드를 작성합니다.

 

>>> viewStockTrend(compcode):

종목코드 compcode를 인자로 받고, 이 인자에 .KS를 추가하여 야후 주식 Open API의 {종목코드} 부분에 대입하고 urlopen() 함수를 이용해 호출합니다.
데이터를 한줄씩 읽은 후 콤마로 구분하고 그 크기가 6인 경우에, 'values'와 'labels'라는 문자가 데이터에 없으면 바로 주식 정보이므로 이것만 읽습니다. Matplotlib으로 해당 데이터를 읽어 차트를 그립니다.

삼성전자의 종목코드인 005930에 대해 위 코드를 실행하면 아래와 같은 주가 트렌드 차트가 화면에 출력됩니다.


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍7 - 파일로부터 데이터를 읽어서 그래프 그리기




첨부한 파일(births.txt)은 1880년부터 2011년까지 미국에서 태어난 남녀 출생아 수를 정리한 데이터입니다.

이 파일은 아래와 같은 형식으로 되어 있습니다.


1880, 90993, 110491
1881, 91954, 100745
1882, 107850, 113688

....

....


각 숫자는 콤마로 구분되어 있고 첫번째 데이터는 년도, 두번째 데이터는 여자 아기 출생수, 세번째 데이터는 남자 아기 출생수입니다.

우리가 해볼 것은 이 데이터를 읽어서 여자 아기와 남자 아기의 출생수 추이를 그래프로 나타내 보고자 합니다.


자, 코드를 바로 보실까요..




>>> import csv


파일로부터 데이터를 편리하게 읽어 들이기 위해 csv 모듈이 제공하는 reader()를 사용할 예정입니다.



>>> years = range(1880, 2012)


년도의 범위는 1880년에서 2011년 까지로 합니다.



>>> with open(datafile, 'rb') as f:

          data = csv.reader(f, delimiter = ',')

          for d in data:

               pieces.append(d)


births.txt 파일을 바이너리 읽기 모드로 열고 그 핸들을 f로 합니다. csv.reader(f, delimiter = ',')은 구분자를 콤마로 해서 파일 f의 데이터를 읽고 구분하여 변수 data에 할당합니다.

data는 [['1880', '90993', '110491'], ['1881', '91954', '100745'], ['1882', '107850', '113688'],....] 와 같은 형식이 됩니다.


x, y1, y2에 각각 data의 첫번째 데이터인 년도, 두번째 데이터인 여자 아기 출생수, 세번째 데이터인 남자 아기 출생수만 따로 모아서 구성합니다.



>>> p1 = plt.plot(x, y1, 'r^--', label='female')

>>> p2 = plt.plot(x, y2, 'bs-', label='male')


데이터를 그래프로 그립니다. plot의 세번째 인자인 'r^--'은 점선으로 연결된 빨간색 삼각형,  'bs-'은 선으로 연결된 파란색 사각형을 의미합니다. 그래프를 그릴 때 마커에 대한 내용은 4편에서 이미 살펴보았습니다.  


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍6 - Matplotlib으로 파이 차트 그리기




파이 차트는 전체를 이루는 각 구성 요소가 전체 중 얼마만큼의 비중으로 되어 있는지 파악하기 매우 좋은 그래프 유형입니다. 바로 코드를 보실까요..




파이 차트를 그리기 위한 데이터는 누적 영역 그래프에서 사용된 어느 사람의 한달 동안 하루 일과 데이터입니다.


>>> activities = ['sleeping', 'working', 'eating', playing']


파이 차트의 라벨을 정의합니다. 이는 데이터 순서와 동일해야 합니다.



>>> n = 11

>>> title = 'Pie Chart for %d day' %(n+1)

>>> plt.title(title)


한 사람의 한달 동안 하루 일과에서 12일 부분을 선택하여 파이 차트를 그릴 예정입니다. 타이틀을 그에 맞게 구성합니다.



>>> slice = [sleeping[n], working[n], earing[n], playing[n]]


파이 차트를 구성하는 슬라이스 데이터를 정의합니다. 한달 데이터에서 12번째 데이터를 각각 취해서 하나의 리스트로 구성합니다.



>>> plt.pie(slice, labels=activities, startangle=90, shadow=True,

                explode=(0, 0, 0.1, 0), autopct='%1.1f%%')


파이 차트를 그려주는 Matplotlib 함수는 plt.pie()입니다. 인자는 다음과 같습니다.


  • slice: 파이 차트를 구성할 데이터
  • labels: 파이 조각의 라벨
  • startangle: 그려지는 파이 조각 시작 위치. 90이면 12시 방향임. 파이 조각은 이 각도를 기준을 반시계 방향으로 그려짐
  • shadow: 파이 차트의 그림자 효과 유무
  • explode: 파이 조각이 돌출되는 크기. 0이면 돌출되지 않음
  • autopct: 파이 조각의 전체 대비 백분율.


코드에서 explode는 3번째 파이 조각을 돌출하게 했습니다. 그리고 autopct에서 파이 조각 백분율은 소수점 1자리까지 %로 표기하도록 했습니다.


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍5 - Matplotlib으로 누적 영역 그래프 그리기



누적 영역 그래프(Stacked Area Graph)는 전체에서 부분이 차지하는 것을 쉽게 보이게 하는 그래프의 한 종류입니다. 이런 목적을 가진 다른 유형의 그래프는 파이 차트입니다. 누적 그래프는 시간의 경과에 따라 각 부분들이 어떻게 변해가는지 살펴보기에 좋은 유형의 그래프인 반면, 파이 차트는 특정 기간 동안 각 부분이 얼만큼 비중을 차지하는가를 살펴보기에 좋은 그래프입니다.


일단 누적 영역 그래프를 그려보겠습니다.




이 코드는 1에서 180도까지 사인 그래프 4개를 누적시킨 그래프를 그립니다.

Matplotlib의 누적 영역 그래프를 그리는 함수는 plt.stackplot() 입니다.


>>> plt.stackplot(days, y1, y2, y3, y4, colors=colors)


x축 방향으로는 days를 위치시키고 y1, y2, y3, y4를 누적하여 그래프를 그립니다. 각 그래프 영역의 색상은 colors로 정의합니다.



보다 실제적인 누적 영역 그래프를 그려보도록 하겠습니다.


어느 한 사람의 하루 일과중 소비하는 시간 추이를 보여주는 그래프를 그리는 코드입니다.




어느 사람의 한달동안 생활 패턴을 분석한 결과를 누적 영역 그래프로 표시하는 코드입니다.

사용한 Matplotlib 함수는 동일하지만, 그래프를 그리기 위한 데이터가 달라졌습니다. sleeping, working, eating, playing의 동일한 위치의 요소들의 합은 모두 24가 됩니다. 하루는 24시간이므로 이 값은 변함이 없어야 겠지요.


playing의 색상은 'k'로 지정했는데, 이는 검정색을 나타냅니다. 


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍4 - Matplotlib으로 산점도 그리기




산점도(Scatter plot)는 2차원 또는 3차원 좌표에 도형으로 표시를 하여 데이터의 상관관계 등을 파악하기 위해 주로 사용됩니다.


아래의 코드는 1에서 100까지 수를 마구 섞어 x좌표, y좌표를 만들고 산점도 결과를 출력하는 코드입니다.




산점도를 그려주는 Matplotlib 함수는 plt.scatter() 입니다. scatter() 함수의 인자는 다양한데, 이 코드에서는 x, y좌표와 라벨, 표시할 도형 종류, 그리고 색상만 인자로 정의했습니다.


산점도에서 표시할 수 있는 도형은 marker= 로 지정하면 되는데, Matplotlib에서 제공하는 마커의 종류는 여기를 참고하세요. 


산점도 그리기를 좀 더 응용해 보겠습니다.




위 코드는 Numpy 배열을 활용하여 50개의 좌표를 무작위로 만들고, 산점도를 원 모양으로 그리되 원의 크기를 무작위로, 원의 색상도 무작위로 해서 그려줍니다.


>>> x = np.random.rand(N)

>>> y = np.random.rand(N)


0에서 1사이의 N개의 수를 무작위로 생성하여 numpy 배열로 구성합니다. 마찬가지로 colors와 area를 50개의 요소를 무작위로 만들어 numpy 배열로 구성합니다. area는 0~15 포인트 사이의 값을 가집니다.



>>> plt.scatter(x, y, label='samples', s=area, c=colors, alpha=0.5)


scatter()의 인자 s는 도형의 크기, c는 도형의 색상, alpha는 색상의 투명도를 지정합니다. alpha의 값이 0이면 완전 투명이고, 1이면 완전 불투명입니다. 


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍3 - Matplotlib으로 막대그래프, 히스토그램 그리기




막대 그래프(Bar Chart)나 히스토그램은 특정 그룹의 데이터의 추세와 정량적인 분포를 파악하는데 매우 유용합니다. 



Matplotlib으로 막대 그래프 그리기

다음과 같은 두 개의 데이터 세트가 있다고 가정합니다.


세트1: (1, 5), (3, 3), (5, 9), (7, 2), (9, 8) 

세트2: (2, 8), (4, 7), (6, 2), (8, 11), (10, 4)


이를 막대 래프로 그리기 위한 코드는 아래와 같습니다.




>>> plt.bar(data_x1, data_y1, label='Set 1', color='b')


Matplotlib에서 막대 그래프를 그리는 함수는 plt.bar() 입니다. 막대의 폭을 지정하지 않으면 막대의 폭이 0.8로 정해집니다. data_x1으로 지정된 좌표에서 폭이 0.8이고 높이가 data_y1, color로 지정된 색상의 막대를 그립니다. Matplotlib에서 색상은 'r'이 Red, 'g'는 Green, 'b'는 Blue를 뜻합니다.


color값으로 #AA2848 처럼 RGB의 색상값으로 표현해도 됩니다.


위 코드에서 Set 2의 막대 그래프 색상을 #AA2848로 저정하여 실행하면 아래와 같은 결과가 나옵니다.




막대의 폭 0.5로 조정하고 싶다면 plt.bar()의 인자로 width = 0.5를 지정하면 됩니다. 아래는 Set 2의 막대그래프 폭을 0.5로 지정하여 출력한 결과입니다.





Matplotlib으로 히스토그램 그리기

히스토그램은 막대그래프와 모양은 비슷하나, 데이터가 있을 때 특정 범위의 값들을 그룹화하여 막대그래프 모양으로 표시하는 것입니다. 예를 들어 아래와 같은 30개의 데이터가 있다고 가정합니다.


22,55,62,45,21,22,34,42,42,4,99,102,110,120,121,122,130,111,115,112,80,75,65,54,44,43,42,48,16,11


이 데이터를 10단위의 간격으로 히스토그램을 그리는 코드는 아래와 같습니다. 


 



Matplotlib에서 히스토그램을 그리는 함수는 plt.hist() 입니다. 위 코드에서 변수 bins는 데이터 분류 기준이 되는 간격을 정의합니다. 여기서는 0~10, 11~20, 21~30,, 과 같이 간격을 10으로 정의했습니다. 히스토그램에서 BIN은 분류하고자 하는 범위라고 생각하면 됩니다. data에 있는 값들을 헤아려서 0~10, 11~20,,, 범위에 있는 개수를 히스토그램으로 나타냅니다. 


결과를 보면 data에 있는 값들 중 0~10 사이에 있는 값은 1개, 60~70사이에 있는 값은 2개임을 알 수 있습니다.


만약, 데이터를 분류하는 범위를 수동으로 지정하지 않고 BIN의 크기로 정해줄 수도 있습니다. data에 있는 값들을 분류하여 BIN의 크기대로 범위를 자동으로 정하고 결과를 화면에 출력하는 것이죠.


위 코드에서 bins = 8로 수정하고 실행하면 아래와 같은 결과가 출력됩니다.




BIN의 크기에 따라 data를 분류하는 값의 범위가 자동적으로 조정되었음을 알 수 있습니다.


이미치 처리를 위해 히스토그램을 응용하기도 하는데, 여기를 눌러 살펴보세요~ 


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍2 - Matplotlib에 제목, 라벨, 레전드 삽입하기




데이터를 분석하고 그 결과만 화면에 출력한다면 이게 무슨 데이터를 분석하여 나온 결과인지 전혀 모를 수 있습니다.

따라서 결과 화면에 제목과 라벨, 레전드 등을 삽입하여 결과를 보는 사용자에게 친절함을 베풀어주는 것이 중요하겠죠.


이번 포스팅에서는 Matplotlib을 이용해 결과를 화면에 출력하되 제목과 라벨, 레전드를 삽입하는 방법에 대해 알아봅니다. 아래는 Jupyter Notebook으로 코딩을 하고 실행한 후 결과를 보인 것입니다.




이 코드는 0도에서 360도 범위에서 삼각함수의 사인함수와 코사인함수의 그래프를 화면에 출력합니다.

plt.plot()에 대해서는 이전 포스팅에서 배웠으므로, 우리의 주제인 제목과 라벨, 레전드 삽입 코드만 살펴보겠습니다.



>>> plt.plot(xs, ys1, label='SIN Curve')

>>> plt.plot(xs, ys2, label='COS Curve')


사인곡선과 코사인곡선을 계산하여 그리되 라벨링을 포함합니다.



>>> plt.xlim([0, 360])


출력할 때 x 값의 범위를 0에서 360도로 제한합니다.



>>> plt.xlabel('X value')

>>> plt.ylabel('Y value')


plt.xlabel()과 plt.ylabel()은 각각 Matplotlib이 출력한 그래프의 x축과 y축에 라벨링하는 함수입니다. 



>>> plt.title('Trigonometric Function')


plt.title()은 Matplotlib이 출력한 결과 화면에 제목을 표시합니다.



>>> plt.legend()


각 곡선에 라벨링한 것을 레전드로 표시합니다.



>>> plt.show()


결과를 화면에 출력합니다.


이제 Matplotlib을 이용한 결과가 좀 풍성해진 것 같네요.. 


반응형
반응형

파이썬 Matplotlib을 이용한 데이터 시각화 프로그래밍1 - Matplotlib 시작하기



요즘 IT업계에서 유행하는 용어가 '빅데이터' 입니다.

빅데이터는 말그대로 용량이 매우 큰 데이터라는 말인데, 좀 더 세밀하게 정의하면 이 의미 의외에 몇가지가 더 있습니다.




아무튼 데이터든 빅데이터든 이들을 분석해서 의미있는 자료로 가공하는 것이 중요한 일이고, 가공된 데이터는 사람이 알아보기 쉽게 시각화(비주얼라이제이션; Visualization) 해주는 것이 중요합니다.


빅데이터 분석을 위한 강좌를 하기 전에 먼저 데이터를 시각화 하는 방법에 대해 살펴보도록 하겠습니다.


먼저 환경은 윈도우 10, 파이썬 3.5.2 입니다. 파이썬 2.7.x 버전을 사용하시는 분들은 일부 코드가 호환되지 않을 수 있으니 참고하세요.


파이썬 라이브러리 Matplotlib은 데이터 분석 결과를 시각화 하는데 필요한 막대 그래프, 선 그래프, 파이 차트, 바 차트 등 다양한 그래프와 차트를 생성하는 함수들을 제공합니다. 일단 Matplotlib을 설치해야 겠네요. 윈도 커맨드창에서 PIP를 이용해 다음과 같이 Matplotlib을 설치하면 필요한 모듈을 모두 알아서 설치해줍니다.


pip install matplotlib


만약 PIP로 matplotlib이 제대로 설치되지 않으면 여기로 가서 차근차근 읽어보고 matplotlib을 설치해보기 바랍니다.


Matplotlib이 제대로 설치되었는지 윈도 명령 프롬프트창에서 파이썬을 실행하고 matplotlib을 import 해봅니다.


>>> import matplotlib


아무 오류없이 import가 되면 성공적으로 설치가 된 것입니다.


자, 그러면 파이썬을 실행하거나 에디터를 이용해 다음과 같이 간단한 코드를 한번 작성해봅니다.


>>> import matplotlib.pyplot as plt

>>> xs = [x for x in range(10)]

>>> ys = [y*y for y in range(10)]

>>> plt.plot(xs, ys)

>>> plt.show()


이 코드는 matplotlib.pyplot을 import 하는데 이 녀석의 별명을 plt로 정의합니다.


plt.plot(xs, ys)는 리스트인 xs와 ys를 이용해 그려야 할 좌표를 정의하고 이 좌표들을 선으로 연결합니다.

xs와 ys는 수가 멤버인 크기가 동일한 리스트여야 합니다.


plt.show()는 결과를 화면에 그려줍니다.


이 코드를 실행하면 아래와 같이 matplotlib 윈도우가 생성되고 결과를 화면에 그려줍니다.




matplotlib 윈도우 아랫부분에는 결과를 다양하게 탐색할 수 있는 버튼들이 있습니다. 마치 인터넷 브라우저의 버튼과 비슷해 보입니다. 맨 왼쪽 집모양은 홈버튼입니다. 결과를 확대하고 축소하고 옮겨다니다가 맨 처음 모양으로 되돌리는 버튼입니다.


화살표 모양의 버튼은 뒤로 가기와 앞으로 가기 버튼입니다. 결과들을 이리저리 보다가 인터넷 브라우저 처럼 이전의 결과를 보고 싶으면 왼쪽 화살표 버튼을, 이후의 결과를 보고 싶으면 오른쪽 화살표 버튼을 이용합니다.


십자가 모양의 화살표는 결과를 이리저리 옮길 수 있다는 것을 표시해주는 아이콘입니다. 결과 화면에 마우스 왼쪽  버튼을 누른 채로 이동하면 결과를 아래 위나 왼쪽 오른쪽으로 이동할 수 있습니다.




결과 화면에 마우스 오른쪽 버튼을 누른채로 움직이면 결과를 확대하거나 축소할 수 있습니다. 아래 그림은 결과를 임의로 축소해본 것입니다.




다섯번째 아이콘을 클릭하면 결과 화면의 특정 부분을 사각형 영역으로 지정하여 확대해 볼 수 있습니다. 아래 그림은 사각형 영역으로 지정한 후 확대한 것입니다.




여섯번째 아이콘을 클릭하면 아래 그림과 같이 그림판의 여백을 조절할 수 있는 게이지가 나타납니다.



아래 그림은 right 여백을 조정한 결과입니다. 게이지 조정에 따른 결과 화면입니다.




이번 포스팅에서는 matplotlib의 기본적인 사항에 대해 가볍게 살펴보았습니다.


참고로 데이터 시각화 프로그래밍2에서는 데이터 분석을 위한 프로그래밍 도구로 많이 활용되는 Jupyter Notebook을 이용할 예정입니다. Jupyter Notebook에 대한 자세한 내용은 아래의 링크를 참조하세요.


Jupyter Notebook 개요 및 설치 


반응형
반응형

그동안 개인적으로 이런저런 일로 바쁘고, 많은 변화가 있어, 정말 오랜만에 포스팅을 하게 됩니다.


이번 포스팅에서는 여태까지 다루어 보았던 머신러닝 및 딥러닝, AI와 관련하여 그 기반이 되는 인공신경망에 대한 간략한 히스토리를 정리해보고자 합니다.

아, 물론 딥러닝의 꽃이라 부를 수 있는 CNN(Convolutional Neural Network)이나 RNN(Recurrent Neural Network) 등에 대해서는 제 블로그에서 아직 다루진 않았습니다만... 이에 대해서는 시간 나는대로 포스팅하도록 하겠습니다.


먼저 아래 그림으로 인공신경망에 대한 간략한 히스토리를 정리해봅니다.





그러면 위 그림을 보면서 인공신경망 발전의 역사를 살포시 살펴봅니다. (내용중 재탕하는 내용도 있으니 참고바랍니다.)


1943년 신경과학자인 Warren S. McCulloch과 논리학자인 Walter Pitts는 하나의 사람 뇌 신경세포를 하나의 이진(Binary)출력을 가지는 단순 논리 게이트로 설명했는데, 이를 McCulloch-Pitts 뉴런(MCP 뉴런)이라 부릅니다.



1957년 코넬 항공 연구소에 근무하던 Frank Rosenblatt은 MCP 뉴런 모델을 기초로 퍼셉트론(Perceptron) 학습 규칙이라는 개념을 고안하게 되는데, Rosenblatt은 하나의 MCP 뉴런이 출력신호를 발생할지 안할지 결정하기 위해, MCP 뉴런으로 들어오는 각 입력값에 곱해지는 가중치 값을 자동적으로 학습하는 알고리즘을 제안했습니다.


1958년 퍼셉트론이 발표된 후 같은 해 7월 8일자 뉴욕타임즈는 앞으로 조만간 걷고, 말하고 자아를 인식하는 단계에 이르는 컴퓨터 세상이 도래할 것이라는 다소 과격한 기사를 냈습니다.

하지만 1969년, 단순 퍼셉트론은 ​XOR 문제도 풀 수 없다는 사실을 MIT AI 랩 창시자인 Marvin Minsky 교수가 증명하였고, 아래 그림과 같은 다층 퍼셉트론(MLP)으로 신경망을 구성하면 XOR 문제를 풀 수 있다고 했습니다. 


그런데, Minsky 교수는 이러한 MLP에서 hidden layer의 가중치를 계산하는, 다시 말하면 MLP를 학습시키는 방법은 존재하지 않는다고 단정해버렸습니다.


이로 인해 떠들석했던 인공신경망과 관련된 학문과 기술은 더 이상 발전되지 않고 암흑기를 겪게 됩니다.


그러다가 1974년, 당시 하버드 대학교 박사과정이었던 Paul Werbos는 MLP를 학습시키는 방법을 찾게 되는데, 이 방법을 Minsky 교수에게 설명하지만 냉랭한 분위기속에 무시되버립니다.


Paul Werbos가 Minsky 교수에게 설명한 MLP를 학습시킬 수 있는 획기적인 방법이 바로 오류 역전파 (Backpropagation of errors)라는 개념입니다. 그냥 줄여서 역전파(Backpropagation)이라 부르기도 하지요.



이런 획기적인 방법 역시 당시 인공신경망의 대가와 학계로부터 무시당해버린 후 Werbos는 1982년 역전파에 대한 내용을 논문으로 발표하고 마무리합니다. Werbos의 역전파가 무시된 이후 10여년 넘게 AI 분야는 혹한기를 겪게 됩니다.


그러다가 1986년 인지심리학자이자 컴퓨터공학자였던 Geoffrey Hinton 교수는 Werbos가 제안한 오류 역전파 알고리즘에 대한 내용을 독자적으로 제안하게 됩니다. 하지만 Werbos가 수 년전에 먼저 논문으로 발표한 내용이기 때문에 Hinton 교수는 역전파 개념을 다시 발견했다고 보는 것이 맞을 겁니다.


그런데 다층구조로 되어 있는 MLP의 학습은 역전파를 통해 학습이 가능하지만 학습의 효과를 크게 하려면 인공신경망의 은닉층(hidden layer)를 많이 쌓아야 더 좋은 결과가 나올 수 있다는 것이 경험적으로 검증되었습니다.


하지만, 당시까지만 해도 활성함수로써 시그모이드 함수를 사용했고, 이는 은닉층의 개수가 많아질수록 역전파에 의한 가중치 계산이 불가능하게 되는 gradient vanishing이라는 문제에 직면하게 되었습니다.


gradient vanishing 문제는 인공신경망 분야의 2번째 암흑기가 시작되는 계기가 되버립니다.


1995년에는 당시 다른 방식으로 발전되었던 보다 단순한 머신러닝 알고리즘인 SVM, RandomForest와 같은 알고리즘이 손글씨 인식 등과 같은 분야에는 더 잘 작동한다고 Lecun 교수 등이 발표하기도 했습니다.

1998년 컴퓨터공학자인 Yann Lecun 교수는 1950년대 수행했던 고양이의 뇌파 실험에 영감을 얻어 이미지 인식을 획기적으로 개선할 수 있는 CNN(Convolutional Neural Network)라는 새로운 형태의 인공신경망을 고안하게 됩니다.




1950년대 수행했던 고양이의 실험은 고양이의 눈으로 보는 사물의 형태에 따라 뇌의 특정영역, 정확히 말하면 특정 뉴런만이 활성화 된다는 것을 알게 된 것입니다. Lecun 교수는 이러한 실험 결과에 영감을 얻어 CNN이라는 새로운 형태의 인공신경망을 고안하게 된 것입니다.




하지만 gradient vanishing 문제 등으로 인해 한동안 인공신경망 분야가 침체기를 겪고 있던 시기에, Hinton 교수와 Bengio 교수는 2006년, 2007년 두 편의 논문을 발표하였는데 초기 입력값을 잘 선택하면 아무리 인공신경망의 층의 개수가 많더라도 학습이 가능하며, 복잡한 문제도 층의 개수가 많게 구성된 인공신경망이라면 해결할 수 있다고 했습니다. 그리고 이렇게 층의 개수가 많은 신경망을 심층신경망(Deep Neural Network:DNN)이라 리브랜딩하고 심층신경망을 학습시키는 방법을 딥러닝(Deep Learning:DL)이라고 명명하게 됩니다.


그리고 2000년 네이처(Nature)지에 시그모이드를 대신하여 사용한 Rectifier라는 활성함수를 이용해 효과를 봤다는 내용의 생물학 분야의 논문이 발표되었습니다. Rectifier는 ReLU(Rectified Linear Unit)라고 불리게 되는 활성함수인데, 이 활성함수를 심층신경망의 딥러닝에 사용해보니 gradient vanishing 문제가 해결되버린 것입니다. 물론 심층신경망의 최종 출력층에서는 여전히 시그모이드나 SoftMax를 사용하지만 말이죠.


아무튼 활성함수 ReLU의 등장으로 딥러닝은 많은 발전을 이루게 되었고, 2012년 이미지 인식 분야의 유명한 대회인 ImageNet Large Scale Visiual Recognition Challenge(ILVRC)에서 캐나다 토론토 대학의 AlexNet이라 불리는 CNN 인공신경망으로 우승하게 되는데, 이전 까지 이미지 인식 오류율이 26%대였던 것이 15%대로 줄이게 된 것입니다.


이후 CNN의 신경망구조가 지속적으로 개선되고 GPU의 발전으로 현재는 5% 이내의 오류율로 학습이 가능하게 되었습니다.




현재 이미지 인식 수준은 아래 그림과 같이 주어진 사진을 설명하는 단계에 이르고 있습니다.



그리고 2016년 알파고가 등장하여 이세돌 9단을 4승1패로 이기면서 세계를 놀라게 했고, 현재는 인공신경망을 이용한 인공지능을 자율주행자동차와 같은 다양한 분야에 적용하고자 노력하고 있는 중입니다.

        


아마, 미래에는 스스로 생각하고 인지하는 인공지능이 탄생할지도 모르지요.



하지만....

아직까지 인공지능과 우리 인간의 뇌는 다릅니다!


  • 인간의 뇌는 약 1천억개의 뉴런과 100조개의 시냅스로 연결되어 있고, 20와트의 전력만으로 충분합니다.
  • 하지만 가장 거대한 인공신경망의 규모는 기껏해봐야 16,000개의 CPU코어상에서 1천만 뉴런과 10억개의 연결로 이루어져 있으며, 소모되는 전력은 3백만와트나 됩니다.
  • 인간의 뇌는 5개의 감각기관으로부터 5가지 유형의 입력만 받습니다.
  • 우리 아기들은 고양이를 학습하는데 라벨링된 10만장의 사진이 필요하지 않습니다.


솔직히 우리는,,, 학습이 이루어지는 우리 뇌의 기작을 잘 알지 못합니다.



이상으로 인공신경망에 대한 히스토리를 가볍게 살펴보았습니다.


아래 영상은 제가 ImageNet으로부터 다운받은 강아지 사진과 꽃 사진을 이용해 tensorflow로 학습을 하고 구글에서 제공해준 템플릿 코드를 이용하여 만들어본 안드로이드 프로그램을 구동한 것입니다.


왼쪽 동영상은 제 스마트폰으로 PC화면에 보이는 강아지와 꽃들을 촬영한 화면을 캡쳐 녹화한 것이고, 오른쪽 동영상은 우리집 강아지와 장미 조화를 스마트폰으로 촬영한 영상을 보인 것입니다. 화면에 표시되는 숫자는 이미지 인식 확률이며 1.0이 100%입니다.  


          


참고로 제 사진 50여장과 무작위 남자 사진 1000여장을 학습시켜본 결과 제 사진을 촬영했을 때 저를 인식한 확률이 매우 높았습니다.  

반응형
반응형

다층 퍼셉트론과 같은 인공신경망을 구현하는 것은 꽤 복잡하고 까다로운 작업이라는 것을 [37편]에서 잠시 느꼈을 것입니다. 그렇다면 우리가 구현한 인공신경망이 제대로 동작하는지, 혹은 정확도가 얼마인지 어떻게 측정해야 할까요?


인공신경망 구현의 핵심은 역전파라고 했으니, 역전파 알고리즘이 얼마나 정확하게 구현되었는지에 대해 검증하면 될 것 같습니다. 역전파 알고리즘을 우리가 직접 수동으로 검증하는 방법이 그라디언트 체킹(gradient checking)이라는 기법입니다.


이번 포스팅에서는 그라디언트 체킹에 대해 가볍게 살펴보고 넘어갑니다.


역전파에서 가중치를 업데이트하기 위해 계산해야 하는 식은 아래의 편미분 식이라는거 이미 알고 있습니다.



여기서 w는 신경망의 모든 가중치에 대한 행렬입니다. 이 미분값을 해석적 그라디언트(Analytical Gradient) 값이라 부릅니다.


도함수의 정의에 의해 해석적 그라디언트는 아래와 같이 표현됩니다.



[식1] 



[식1]의 오른쪽 항에서 ε이 매우 작은 값이라 할 때, 아래의 값으로 근사됩니다.



[식2] 



[식2]의 오른쪽 항의 값을 수치적 그라디언트(Numerical Gradient) 값이라 부릅니다.


아래 그림은 수치적 그라디언트의 기하학적인 의미를 나타낸 것입니다.


 



[식2]에서 ε을 -ε으로 바꾸어보면 아래의 식이 됩니다.



[식3]


[식2]와 [식3]의 양 변을 각각 더하면 아래의 식이 됩니다.




따라서,



[식4]



[식4]의 오른쪽 항을 새롭게 정의한 수치적 그라디언트로 채택합니다. 실제로 새롭게 정의한 수치적 그라디언트가 해석적 그라디언트와의 오차가 더 작게 나옵니다. 


수치적 그라디언트를 J'n 이라 하고 해석적 그라디어트를 J'a라 하면 절대오차 Err와 상대오차 Rerr는 다음과 같이 정의합니다.



[식5]






이 식에서 || ||는 행렬의 놈(norm)이며 행렬의 놈은 행렬의 모든 성분을 p제곱하여 더한 값의 p제곱근으로 정의됩니다.

n x m 행렬 A가 다음과 같을 때,

행렬 A의 놈은 아래와 같이 정의됩니다.



여기서 p=2인 경우를 프로베니우스 놈이라 부르며 가장 일반적으로 많이 사용되는 행렬 놈입니다.


우리가 구현한 역전파 알고리즘의 정확도는 해석적 그라디언트와 수치적 그라디언트의 상대 오차값으로 평가합니다. 역전파 알고리즘의 정확도를 평가하는 측도로써 절대 오차를 사용하지 않는 이유는 Err가 매우 작은 값이더라도 J'nJ'a  값 자체가 매우 작다면 상대적으로 오차율이 커지기 때문입니다.



상대오차 Rerr의 값에 따른 역전파 알고리즘의 정확도는 일반적으로 아래와 같은 규칙을 따릅니다.




이 규칙에 따라 [37편]에서 구현한 MLP를 검증해보도록 합니다.


아래의 코드를 [37편]의 dl_mlp_class.py에서 구현한 NeuralNetMLP 클래스의 메쏘드로 추가합니다.




이 코드는 [식5]의 Rerr를 계산하여 리턴하는 함수를 구현한 것입니다. 코드를 보면 그렇게 어려운 부분이 없습니다.


NeuralNetMLP 클래스의 fit() 메쏘드에서 역전파를 통해 경사를 계산하는 코드를 찾습니다.



이 코드 다음에 아래의 코드를 추가합니다.




그라디언트 체크 기능이 추가된 NeuralNetMLP 클래스가 완성되었습니다. 이제 아래의 코드를 작성합니다.




이 코드는 X_train, y_train의 5개 데이터에 대한 10회 학습의 그라디언트 체킹을 수행한 결과를 화면에 출력합니다. 시간이 제법 소요되므로 너긋하게 기다리면서 결과를 지켜보도록 합니다.


코드를 수행한 결과는 다음과 같습니다.


Warning: 3.537822909e-07
OK: 3.02628344172e-10
OK: 3.02609921621e-10
OK: 3.06158619281e-10
OK: 3.21874437906e-10
OK: 3.27658507646e-10
OK: 2.87684685361e-10
OK: 2.32833603418e-10
OK: 2.52932883134e-10
OK: 2.70109334393e-10



1회 학습을 빼고 2회~10회까지 그라디언트 체킹 결과는 매우 훌륭하다는 것을 알 수 있습니다. 따라서 [37편]에서 구현한 역전파 알고리즘은 제대로 구현한 것이라고 판단할 수 있습니다.


체킹이 마무리되면 fit()에 추가한 그라디언트 체킹 수행 코드를 주석 처리 해둡니다. 


반응형

+ Recent posts

반응형