※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 08. Advanced Visualization (고급 시각화)


다양한 데이터 구조와 알고리즘을 이해하기 쉽도록 시각화 가능하다. 다음 사이트들에 좋은 예시들이 풍부하게 수록되어 있다.
https://visualgo.net/en
https://www.cs.usfca.edu/~galles/visualization

Computer Simulation (컴퓨터 시뮬레이션)

컴퓨터 시뮬레이션의 모델은 알려지지 않거나 분석이 어려운 시나리오를 이해하고 평가하기 위한 방법으로서, 지난 수십 년 이상 인기를 얻은 학문이다.

또한, 컴퓨터 시뮬레이션은 물리학, 화학, 생물학, 경제학, 공학, 심리학, 사회 과학 등 다양한 분야에서 시스템의 수학적 모델링에 매우 생산적인 방법이다.


컴퓨터 시뮬레이션 모델의 장점

- 연구되고 있는 알고리즘 또는 프로세스에 대한 이해의 향상

- 프로세스 및 알고리즘의 문제 영역을 식별

- 알고리즘 / 모델에 관한 특정 변화에 대한 영향력 평가


컴퓨터 시뮬레이션 모델의 유형

- 이산 모델 : 특정 시간에 발생한 시스템의 변화들

- 연속 모델 : 일정 기간에 걸쳐 연속적으로 변화하는 시스템의 상태

- 혼합 모델 : 이산과 연속 요소를 모두 포함


시뮬레이션을 수행하기 위해, 일반적으로 임의의 확률적 입력 값을 사용한다. 이는 시뮬레이션 모델에 대응하는 실제 데이터를 갖기 어려워서이다.



#. Python's Random Package (파이썬의 랜덤 패키지)

파이썬은 여러 편리한 함수들을 가진 random 이라는 패키지를 제공한다.


- 0.0 ~ 1.0 사이 또는 특정 시작과 끝 값 사이의 임의 랜덤 실수(real numbers) 생성

- 숫자의 특정 범위 사이의 임의 랜덤 정수(integers) 생성

- 숫자 또는 문자 목록에서 임의 랜덤값 생성


import random


print random.random() # between 0.0 and 1.0

print random.uniform(2.54, 12.2) # between 2.54 and 12.2

print random.randint(5,10)  # random integer between 5 and 10


print random.randrange(25)  # random number between 0 and 25


#  random numbers from the range of 5 to 500 with step 5

print random.randrange(5,500,5) 


# three random number from the list 

print random.sample([13,15,29,31,43,46,66,89,90,94], 3) 


# Random choice from a list

random.choice([1, 2, 3, 5, 9])



#. SciPy's Random Functions (SciPy의 랜덤 함수)

알고리즘과 수학적 기술을 가진 NumPy 의 확장 버전이 SciPy 패키지다.


NumPy는 Built-in Pseudo Random 생성기를 제공한다. 숫자들은 Pseudo 랜덤이다.

즉, 하나의 Seed 숫자로부터 결정성을 갖고 생성된다. 따라서 같은 Seed 번호를 사용하면 같은 랜덤 숫자들을 생성할 수 있음을 참고하자.


import numpy as np

np.random.seed(10)


각기 다른 랜덤 시퀀스는 Seed 값을 설정하지 않음으로써 생성할 수 있다.

NumPy는 자동으로 랜덤 Seed를 시간 기준으로 선택한다.


np.random.seed()


구간 [0.0, 1.0] 에서 5개의 랜덤값 배열을 다음과 같이 생성할 수 있다.


np.random.rand(5)


Out[]: array([ 0.54340494,  0.27836939,  0.42451759,  0.84477613,  0.00471886])


rand 함수를 이용해 다음 코드처럼 임의의 2차원 배열을 생성할 수 있다.


np.random.rand(2, 4)


Out[]: 

array([[ 0.12156912,  0.67074908,  0.82585276,  0.13670659],

       [ 0.57509333,  0.89132195,  0.20920212,  0.18532822]])


임의의 랜덤 정수를 생성하기 위해 randint(min, max)를 사용할 수 있다.

min과 max는 임의 랜덤 정수를 선택하기 위한 범위다.


np.random.randint(4, 18)


Out[]: 13


Lambda = 8.0 을 가진 이산 포아송 분포(Discrete Poisson distribution)의 임의 랜덤 값은 다음과 같이 생성할 수 있다.


np.random.poisson(8.0)


Out[]: 3


표준편차(sigma) = 3.0, 평균(mu) = 1.25 를 가진 연속 정규분포(Gaussian distribution)의 임의 랜덤 값은 다음과 같이 생성할 수 있다.


np.random.normal(1.25, 3.0)


Out[]: 0.5128392013916669



#. Simulation Examples (시뮬레이션 예제)

첫 번째 예제는 확률 미분 방정식(SDE)로 주가 변동을 모델링하기 위한 기하학적 브라운 운동(Geometric Brownian Motion)이다.

기하학적 브라운 운동은 지수 브라운 운동(Exponential Brownian Motion)으로도 알려져 있다.


위 수식에서 W_t 는 브라운 운동을, mu는 percent drift, sigma는 percent volatility(변동성) 이다.


다음 코드는 브라운 운동을 시각화한 것이다.


from numpy.random import standard_normal

from numpy import zeros, sqrt

import matplotlib.pyplot as plt


S_init = 20.222

T = 1

tstep = 0.0002

sigma = 0.4

mu = 1

NumSimulation = 6


colors = [ (214,27,31), (148,103,189), (229,109,0), (41,127,214), 

(227,119,194),(44,160,44),(227,119,194), (72,17,121), (196,156,148) ]  


# Scale the RGB values to the [0, 1] range.  

for i in range(len(colors)):  

    r, g, b = colors[i]  

    colors[i] = (r / 255., g / 255., b / 255.)  

    

plt.figure(figsize=(12,12))


Steps = round(T/tstep); #Steps in years

S = zeros([NumSimulation, int(Steps)], dtype=float)

x = range(0, int(Steps), 1)


for j in range(0, NumSimulation, 1):

    S[j,0]= S_init

    for i in x[:-1]:

       S[j,i+1]=S[j,i]+S[j,i]*(mu-0.5*pow(sigma,2))*tstep+ \

          sigma*S[j,i]*sqrt(tstep)*standard_normal()

    plt.plot(x, S[j], linewidth=2., color=colors[j])


plt.title('%d Simulation using %d Steps, \n$\sigma$=%.6f $\mu$=%.6f $S_0$=%.6f '

          % (int(NumSimulation), int(Steps), sigma, mu, S_init), fontsize=18)

plt.xlabel('steps', fontsize=16)

plt.grid(True)

plt.ylabel('stock price', fontsize=16)

plt.ylim(0,90)


plt.show()



추가로, 아래 사이트에서 신경망 시뮬레이션 모델링을 수행할 수 있는 파이썬 패키지를 구할 수 있다.

http://briansimulator.org



Animation (애니메이션)

파이썬에서 matplotlib 을 이용해 애니메이션을 만들 수 있다. 

우선, 애니메이션을 생성하기 위한 기본 코드는 다음과 같다.


import numpy as np 

import matplotlib.pyplot as plt 

from matplotlib import animation  


# Set up the figure, axis, and the plot element to be animated 

fig = plt.figure() 

ax = plt.axes(xlim=(0, 3.2), ylim=(-2.14, 2.14)) 

line, = ax.plot([], [], lw=2)


matplotlib 에서 애니메이션 패키지를 정확히 불러오기 위해 다음과 같이 축을 설정하고, 필요한 도식화 변수(비어있는 선)를 준비한다.


# initialization function: plot the background of each frame

def init():

    line.set_data([], [])

    return line,


다음과 같이 모든 애니메이션을 시작하기 전 기본 프레임을 만든다.


# animation function.  This is called sequentially

def animate(i):

    x = np.linspace(0, 2, 1000)

    xval = 2 * np.pi * (x - 0.01 * i)

    y = np.cos(xval) # Here we are trying to animate cos function

    line.set_data(x, y)

    return line,


여기에 입력인 x 와 y 값이 변하는 것으로 정의된 프레임 번호, 도식화되는 변수들의 집합들을 포함하는 에니메이션 함수를 사용한다.


anim = animation.FuncAnimation(fig, animate, init_func=init,\

            frames=200, interval=20, blit=True)

anim.save('basic_animation.html', fps=30)


실제 애니메이션 개체는 FuncAnimation 을 통해서 만들어지며,

init()와 animate() 함수에게 프레임의 개수인 fps(frames per second)와 시간 간격 파라미터를 통해 전달된다.

blit=True 파라미터는 바뀌는 부분만 다시 그려지면서 표시하는 것을 의미한다.


더 많은 예제들은 다음 블로그에서 확인할 수 있다.

http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/

http://matplotlib.org/examples/animation/


※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 07. Bioinformatics, Genetics and Network Models (생물정보학, 유전학, 네트워크 모델)


이 장에서는 예제들을 다루기 위해 metaseq, NetworkX, matplotlib, Biopython, ETE toolkit 과 같은 라이브러리들을 사용한다.

Directed Graphs and Multigraphs (방향성 그래프와 멀티 그래프)

그래프와 방향성 그래프의 활용성을 알아보기 위해, 간단한 예를 생각해보자.


대학 캠퍼스 지역 내 서로 연결된 컴퓨터는 연결 그래프로 생각할 수 있고, 이 연결 안에서 각 컴퓨터는 노드(Node)나 정점(Vertex)이라 볼 수 있다.

연결된 길은 모서리이고, 어떤 경우 오직 한 방향 연결만 있다면 그것이 방향성 그래프이다.

또 다른 예로, 매우 엄격한 연방 네트워크는 밖에서부터 안으로 들어오는 어떤 연결도 허락하지 않을 것이나, 아마 반대로는 제약이 없을 것이다.


다음 간단한 그래프는 각 장소들 간의 거리를 보여준다.


앞의 예시에서 A부터 F까지 이름 붙여진 도시의 그래프는 방향성 그래프이고, 오른쪽 다른 그래프는 방향성이 없는 그래프이다.

방향성 그래프에서 화살표 방향이 양쪽으로 되어 있다면, 두 방향으로 갈 수 있는 길이 존재하는 것이다.

한편, 비방향성 그래프에서는 양쪽 방향 모두 가정한다. (오른쪽 그래프)


이러한 그래프들을 어떤 데이터 구조를 사용해 표현해야 할까?



#. Storing Graph Data (그래프 데이터 저장)

그래프 데이터는 보통 희소 행렬이나 인접 행렬로 나타내진다.

인접 행렬은 그래프가 V개의 정점(Vertex) 또는 노드(Node)를 갖는다고 가정했을 때, V2개 행을 갖는 행렬이다.


예를 들어, 앞에서 본 두 그래프들은 다음 표와 같은 인접 행렬이다.


 

25 

26 

 

 

 

 

85 

10 

 

26 

85 

 

 

10 

 

 

 

 

11 

 

 

 

88 

 

 

 

11 

88 


 

Chicago 

Boston 

New York 

Wash DC 

Miami 

Dallas 

Chicago 

1613 

 

1145 

 

 

Boston 

1613 

338 

725 

 

 

New York 

 

338 

383 

2145 

 

Wash DC 

1145 

725 

383 

1709 

2113 

Miami 

 

 

2145 

1709 

2161 

Dallas 

 

 

 

2113 

2161 


비방향성 그래프는 대칭적으로 저장공간의 반 정도를 사용하는 것으로 충분하다.

행렬의 빈 성분들은 거리에 관한 충분한 데이터가 있지 않음을 보여준다.


scipy에는 희소 행렬을 편리하게 다룰 수 있는 함수들이 존재한다.

다음 코드는 앞 그림의 첫 그래프에 해당한다.


import scipy.sparse as sparse


matrixA = sparse.lil_matrix((6,6))


matrixA = sparse.lil_matrix([

        [0,25,26,0,0,0],

        [0,0,85,5,10,0],

        [26,85,0,0,0,10],

        [0,0,0,0,0,11],

        [0,0,0,9,0,88],

        [0,0,0,11,88,0]

        ])


print matrixA


  (0, 1)        25

  (0, 2)        26

  (1, 2)        85

  (1, 3)        5

  (1, 4)        10

  (2, 0)        26

  (2, 1)        85

  (2, 5)        10

  (3, 5)        11

  (4, 3)        9

  (4, 5)        88

  (5, 3)        11

  (5, 4)        88


그래프를 보여주기 위해 사용할 수 있는 방대한 파이썬 패키지가 있다. 그 중 많이 사용되고 있는 TOP 3는 NetworkX, igraph, graph-tool 이다.



#. igraph

원래 igraph는 R 언어를 위해 만들어졌는데, 후에 파이썬 버전이 추가됐다.

igraph는 dimacs, dl, edgelist, graml, graphdb, gml, lgl, ncol, pajek 등 몇 가지 포맷들을 제공한다.


GraphML은 XML 기반 파일 포맷이며 큰 그래프에 사용될 수 있다.

NCOL 와 LGL 그래프 포멧은 Weighted Edge List를 가진 큰 그래프에 적합하다.

다른 대부분의 포맷들은 간단한 원문 포맷을 사용한다.

DL 파일 포맷만 igraph에 의해 모두 지원되며, 다른 포맷들은 부분적으로 지원한다.


igraph의 장점은, 편리하며 SVG 포맷으로 결과를 저장해 HTML 파일에 내장할 수 있다는 것이다.

(Anaconda Prompt에서 win-64(Microsoft Windows 64bit OS) 환경에서 다음 명령어를 통해 igraph를 설치할 수 있습니다.)


conda install -c vtraag python-igraph


이제, pajek 포맷을 포함하는 예제를 살펴보자. (http://vlado.fmf.uni-lj.si/pub/networks/pajek/ 참고)


import igraph


vertices = ["A", "B", "C", "D", "E"]


edges = [(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,1),

         (1,8),  (8,2),(2,4),(4,9),(9,5),(5,7),(7,0)]


graphStyle = { 'vertex_size': 20}

g = igraph.Graph(vertex_attrs={"label": vertices}, edges=edges, directed=True)

g.write_svg("simple_star.svg", width=500, height=300, **graphStyle)



다음은 파일로부터 그래프 데이터를 읽는 예제 코드이다.

(http://vlado.fmf.uni-lj.si/pub/networks/pajek/data/gphs.htm 에서 데이터 다운로드 가능)


from igraph import read  


g=read("Ragusa18.net",format="pajek")  

  

g.vs["color"]="#3d679d" 

g.es["color"]="red" 


graphStyle={ 'vertex_size': 12, 'margin': 6} 

#graphStyle["layout"]=g.layout("fr")  # optional


g.write_svg("ragusa_graph.svg", width=600, height=600,**graphStyle)



같은 데이터셋에서 다음 코드처럼 원형 모양 등의 레이아웃 옵션을 선택적으로 할당할 수 있다.


graphStyle["layout"]=g.layout("circle")




#. NetworkX

다음은 matplotlib을 통해 방향성 그래프를 만든 예제 코드이다


import matplotlib.pyplot as plt

import pylab

from pylab import rcParams


import networkx as nx


# set the graph display size as 10 by 10 inches

rcParams['figure.figsize'] = 10, 10


G = nx.DiGraph()


# Add the edges and weights

G.add_edges_from([('K', 'I'),('R','T'),('V','T')], weight=3)

G.add_edges_from([('T','K'),('T','H'),('T','H')], weight=4)


# these values to determine node colors

val_map = {'K': 1.5, 'I': 0.9, 'R': 0.6, 'T': 0.2}

values = [val_map.get(node, 1.0) for node in G.nodes()]


edge_labels=dict([((u,v,),d['weight'])

                 for u,v,d in G.edges(data=True)])


#set edge colors

red_edges = [('R','T'),('T','K')]

edge_colors = ['green' if not edge in red_edges else 'red' for edge in G.edges()]


pos=nx.spring_layout(G)


nx.draw_networkx_edges(G,pos,width=2.0,alpha=0.65)

nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)


nx.draw(G,pos, node_color = values, node_size=1500,

 edge_color=edge_colors, edge_cmap=plt.cm.Reds)


pylab.show()

nx.is_directed_acyclic_graph(G) 

.


이 그래프는 NetworkX를 사용해 그래프의 시각미와 모서리 굵기를 조절한 것이다.

방향성 그래프를 보여주는 여러 방법 중 NetworkX는 방향을 화살표 대신 끝을 두꺼운 막대로 표시한다.


추가로 최단 경로부터 연결수 분포, 클러스터링 계수까지 NetworkX는 다양한 그래프 분석 방법을 제공한다.
다음 코드는 최단 경로를 보여주는 간단한 예제 코드이다.

import networkx as nx


g = nx.Graph()

g.add_edge('m','i',weight=0.1)

g.add_edge('i','a',weight=1.5)

g.add_edge('m','a',weight=1.0)

g.add_edge('a','e',weight=0.75)

g.add_edge('e','h',weight=1.5) 

g.add_edge('a','h',weight=2.2)


nx.draw(g)


print nx.shortest_path(g,'i','h')


['i', 'a', 'h']


다음 예제는 레미제러블 소설에 등장하는 인물들의 관계를 나태낸다.

(https://gephi.org/datasets/lesmiserables.gml.zip 으로부터 데이터셋을 받을 수 있으며, GML 포맷 데이터로 되어있다.)


import networkx as nx

from pylab import rcParams

rcParams['figure.figsize'] = 12, 12


G = nx.read_gml('./lesmiserables.gml')

G8 = G.copy()

dn = nx.degree(G8)


#for n in G8.nodes():

#  if dn[n] <= 8:

#    G8.remove_node(n)


pos= nx.spring_layout(G8)

nx.draw(G8, node_size=10, edge_color='b', alpha=0.45, font_size=9, pos=pos)

labels = nx.draw_networkx_labels(G8, pos=pos)




#. The Planar Graph Test (평면 그래프 테스트)

평면 그래프는 교차하는 가장자리(Intersecting Edge) 없이 평면에 그려질 수 있는 그래프이다.

평면 그래프를 그리기 위해 정점으로부터 시작해 가장자리(edge)와 엣지(edge)를 그리고, 그려지는 면(face)들을 계속해서 추적해야 한다.


다음은 평면 그래프의 간단한 예이다.



오일러의 공식은 정점, 가장자리(edge), 면(face)들을 연결한다.

오일러에 따르면, 유한 연결 평면 그래프(Finite and Connected Planar Graph)가 교차하는 가장자리(edge) 없이 평면에 그려졌을때 다음 식이 성립한다.

v - e + f = 2 (v : 정점의 수, e = 가장자리 수, f = 면의 수)



#. The Directed Acyclic Graph Test (방향성 비순환 그래프 테스트)

방향성 비순환 그래프(DAG, Directed Acyclic Graph)란, 예로 정점 A로부터 B로의 엣지들은 특정 방향(A -> B or B -> A)을 지시하고 비순환성을 지닌다.

비순환 그래프는 순환이 없다. 다시말해, 사이클이 없는 것을 의미한다.


NetworkX 패키지의 is_directed_acyclic_graph(Graph)는 시각화의 맥락에서 그래프가 비순환인지 아닌지를 체크하는 방법을 제공한다.


import matplotlib.pyplot as plt

import pylab

from pylab import rcParams


import networkx as nx


# set the graph display size as 10 by 10 inches

rcParams['figure.figsize'] = 10, 10


G = nx.DiGraph()


# Add the edges and weights

G.add_edges_from([('K', 'I'),('R','T'),('V','T')], weight=3)

G.add_edges_from([('T','K'),('T','H'),('T','H')], weight=4)

# these values to determine node colors

val_map = {'K': 1.5, 'I': 0.9, 'R': 0.6, 'T': 0.2}

values = [val_map.get(node, 1.0) for node in G.nodes()]


edge_labels=dict([((u,v,),d['weight'])

                 for u,v,d in G.edges(data=True)])


#set edge colors

red_edges = [('R','T'),('T','K')]

edge_colors = ['green' if not edge in red_edges else 'red' for edge in G.edges()]


pos=nx.spring_layout(G)


nx.draw_networkx_edges(G,pos,width=2.0,alpha=0.65)

nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)


nx.draw(G,pos, node_color = values, node_size=1500,

 edge_color=edge_colors, edge_cmap=plt.cm.Reds)


pylab.show()


nx.is_directed_acyclic_graph(G) 


True




#. Maximum Flow and Minimum Cut (최대 플로우와 최소 컷)

'플로우 네트워크'는 소스로부터 목적지까지 방향성을 가진 그래프이며 각 엣지를 따라 할당된 용량(Capacity)이 주어진다.

최단 경로를 찾기 위해 방향성 그래프로 거리 지도를 모델링하는 것과 비슷하게, 플로우 네트워크로 방향성 그래프를 해석할 수 있다.

예시로는 파이프를 통해 흐르는 액체, 전기 네트워크를 통과하는 전류, 데이터 통신 네트워크를 통해 전송되는 데이터 등이다.



그래프 G의 엣지들은 엣지가 얼만큼의 플로우를 지원할 수 있는지에 대한 용량을 가지고 있다. 용량이 없다면 무한으로 가정한다.

위 그래프에서 플로우 네트워크 G의 최대 플로우는 4이다.


NetworkX 패키지의 maximum_flow_value(Graph, from, to)는 그래프의 최대 플로우를 계산한다.


import networkx as nx

G = nx.DiGraph()

G.add_edge('p','y', capacity=5.0)

G.add_edge('p','s', capacity=4.0)

G.add_edge('y','t', capacity=3.0)

G.add_edge('s','h', capacity=5.0)

G.add_edge('s','o', capacity=4.0)


flow_value = nx.maximum_flow_value(G, 'p', 'o')


print "Flow value", flow_value


Flow value 4.0


...

※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 06. Statistical and Machine Learning (통계 및 머신러닝)


최근 머신러닝은 인공지능에서 가장 중요한 부분이 됐다.
연산 속도 등 컴퓨팅 성능의 발전으로 인해, 머신러닝을 통해 인공지능 시스템을 구축할 수 있게 될 가능성이 매우 높아졌다.

Linear Regression (선형 회귀)

선형 회귀분석은 주어진 입력변수(X)와 반응변수(Y)간의 관계를 선형 관계식으로 모형화하는 것이다.

다음 주어진 데이터에 대해 선형 회귀분석을 실시. 목표 응답변수(target response variable, Y)는 acceptance 이다.



import pandas as pd

import statsmodels.formula.api as smf

from matplotlib import pyplot as plt


df = pd.read_csv('./sports.csv', index_col=0)

fig, axs = plt.subplots(1, 3, sharey=True)

df.plot(kind='scatter', x='sports', y='acceptance', ax=axs[0], figsize=(16, 8))

df.plot(kind='scatter', x='music', y='acceptance', ax=axs[1])

df.plot(kind='scatter', x='academic', y='acceptance', ax=axs[2])


# 적합된 모형을 생성

lm = smf.ols(formula='acceptance ~ music', data=df).fit()


X_new = pd.DataFrame({'music': [df.music.min(), df.music.max()]})

preds = lm.predict(X_new)


df.plot(kind='scatter', x='music', y='acceptance', figsize=(12,12), s=50)


plt.title("Linear Regression - Fitting Music vs Acceptance Rate", fontsize=20)

plt.xlabel("Music", fontsize=16)

plt.ylabel("Acceptance", fontsize=16)


# 최소제곱선 도식화

plt.plot(X_new, preds, c='red', linewidth=2)




선형 회귀분석을 사용하기 위한 많은 수학적 파이썬 라이브러리들이 있다.

주로 scikit-learn, seaborn, statsmodels, mlpy 들이 사용되고 기억할 만한 것들이다.

참고 : http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html




Decision Tree (의사결정나무)

날씨에 따라 야외활동을 하는 것이 좋은가 나쁜가의 예제를 살펴본다.


from sklearn.externals.six import StringIO

from sklearn import tree

import pydot 


X=[[1,1,1,0],[1,1,1,1],[2,1,1,0],[2,3,2,1],[1,2,1,0],[1,3,2,0],\

[3,2,1,0],[3,3,2,0],[3,3,2,1],[3,2,2,0],[1,2,2,1],[2,2,1,1],\

[2,1,2,0],[3,2,1,0]]  


Y=[0,0,1,1,0,1,1,1,0,1,1,1,1,0] 


clf = tree.DecisionTreeClassifier()

clf = clf.fit(X, Y)


dot_data = StringIO() 

tree.export_graphviz(clf, out_file=dot_data) 


graph = pydot.graph_from_dot_data(dot_data.getvalue()) 

graph.write_pdf("game.pdf")




Naive Bayes Classifier (나이브 베이즈 분류기)

나이브 베이즈 분류법의 선행으로 베이즈 정리를 이해할 필요가 있다.


#. 베이즈 정리 (The Bayes Theorem)

다음 그림처럼 모든 사람이 U라는 전체 공간에 속하고,

유방암에 걸린 사람들의 집합을 A, 표본 검사에서 유방암으로 진단 받은 사람들의 집합을 B라고 가정하면 A∩B의 교집합이 존재한다.



2개의 다른 공간에 주목할 필요가 있다.

(1) B - A∩B : 유방암 진단에서 양성 판정을 받았으나, 실제 유방암에 걸리지 않은 집단

(2) A - A∩B : 유방암 진단에서 음성 판정을 받았으나, 실제 유방암에 걸린 집단


여기서 우리가 알고 싶은 정보가, 양성 판정을 받은 사람이 실제로 유방암에 걸렸을 확률이라고 하자.

수학적으로 표현한다면, B(유방암 진단을 받음)가 주어졌을 때 A(실제 유방암에 걸림)인 조건부 확률이라고 할 수 있다.



(즉, B에 대한 정보가 있기 때문에 확률 계산의 전체 공간이 U에서 B로 좁혀지게 되는 것입니다.)


비슷하게, 암을 가지고 있는 사람에 대해 알고 있을 때 암진단 테스트가 양성 반응으로 나올 확률은 다음과 같다.



따라서, 베이즈 정리를 다음과 같이 유도할 수 있다.



이 베이즈 정리는 A와 B 사건에 대해 B가 일어날 확률이 0이 아닐 경우에 유용하다.



#. 나이브 베이즈 분류기 (Naive Bayes Classifier)

나이브 베이즈 분류 기법은 입력 자유도(변수의 개수)가 높을 때 사용하기 적절하다.

상대적으로 간단하지만, 좋은 성능을 나타낸다.

(참고 : http://scikit-learn.org/stable/modules/naive_bayes.html 및 http://sebastianraschka.com/Articles/2014_naive_bayes_1.html )


다음 예제를 살펴보자.


빨간색 : 유방암에 걸린 집단

파란색 : 양성 진단을 받은 집단

흰색    : 새로운 사람



이 데이터를 통해 우리가 알 수 있는 정보는 다음과 같다.




#. TextBlob 라이브러리를 활용한 나이브 베이즈 분류기

TextBlob은 문자처리를 위한 도구들의 모음이다.

또한, NLP(자연어 처리, Natural Language Processing)를 위한 API를 제공해 분류, 명사구 추출, 대화 일부분 태깅, 감정 분석 등을 할 수 있다.


아나콘다 프롬포트(Anaconda Prompt)에서 다음 명령어를 통해 TextBlob를 설치할 수 있습니다.

conda install -c conda-forge textblob


그 다음, 예제 분석을 위한 말뭉치(Corpus)를 다음과 같이 다운받을 수 있다. (이 또한 하나콘다 프롬포트에서 진행합니다.)


python -m textblob.download_corpora


TextBlob을 이용해 고유의 문자 분류기를 쉽게 만들 수 있다.

TextBlob 0.6.0 버전 기준으로 다음 분류기들을 사용할 수 있다.


- BaseClassifier

- DecisionTreeClassifier

- MaxEntClassifier

- NLTKClassifier

- NaiveBayesClassifier

- PositiveNaiveBayesClassifier


다음 예제는 NaiveBayesClassifier를 활용한 감성 분석이다.


from textblob.classifiers import NaiveBayesClassifier

from textblob.blob import TextBlob


train = [

    ('I like this new tv show.', 'pos'),

    ('This is a very exciting event!', 'pos'),

    ('I feel very good about after I workout.', 'pos'),

    ('This is my most accomplished work.', 'pos'),

    ("What an awesome country", 'pos'),

    ("They have horrible service", 'neg'),

    ('I do not like this new restaurant', 'neg'),

    ('I am tired of waiting for my new book.', 'neg'),

    ("I can't deal with my toothache", 'neg'),

    ("The fun events in costa rica were amazing",'pos'), 

    ('He is my worst boss!', 'neg'),

    ('People do have bad writing skills on facebook', 'neg')

]

test = [

    ('The beer was good.', 'pos'),

    ('I do not enjoy my job', 'neg'),

    ("I feel amazing!", 'pos'),

    ('Mark is a friend of mine.', 'pos'),

    ("I can't believe I was asked to do this.", 'neg')

]


cl = NaiveBayesClassifier(train)

print(cl.classify("The new movie was amazing."))  # "pos"

print(cl.classify("I don't like ther noodles."))   # "neg"


print "Test Results"

cl.update(test)


# Classify a TextBlob

blob = TextBlob("The food was good. But the service was horrible. "

                "My father was not pleased.", classifier=cl)

print(blob)

print(blob.classify())


for sentence in blob.sentences:

    print(sentence)

    print(sentence.classify())


# Compute accuracy

print("Accuracy: {0}".format(cl.accuracy(test)))


# Show 5 most informative features

cl.show_informative_features(10)




Viewing Positive Sentiments using Word Clouds (워드클라우드를 이용해 긍정적인 감정 분석)

워드클라우드는 문서에 대한 각 단어들의 빈도를 잘 표현하는 것으로 매우 유명하다.

단어의 등장 횟수에 따라 글자의 크기를 바꿔 시각화한다. 가장 자주 나타난 단어의 크기가 가장 크게 표현된다.


아나콘다 프롬포트(Anaconda Prompt)에서 다음 명령어를 통해 wordcloud 패키지를 설치할 수 있습니다.

conda install -c conda-forge wordcloud


다음 예제 코드에서 STOPWORDS 는 a, an, the, is, was, at, in 과 같은 분석적으로 의미 없는 단어들을 제외하기 위한 단어 모음이다.


from wordcloud import WordCloud, STOPWORDS

import matplotlib.pyplot as plt

from os import path


d = path.dirname("__file__")

text = open(path.join(d, './results.txt')).read()


wordcloud = WordCloud(

    #font_path='/Users/MacBook/kirthi/RemachineScript.ttf',

    stopwords=STOPWORDS,

    background_color='#222222',

    width=1000,

    height=800).generate(text)


# Open a plot of the generated image.

plt.figure(figsize=(13,13))


plt.imshow(wordcloud)

plt.axis("off")


plt.show()




#. K-근접 이웃 (K-nearest Neighbors, KNN)

KNN 분류법은 가장 이해하기 쉬운 분류 방법 중에 하나이며, 부분적으로 데이터 분포의 사전 정보가 적거나 없을 때 사용된다.


사과, 배, 그리고 바나나 분류에 대한 다음 데이터와 예제를 살펴보자.



import csv

import matplotlib.pyplot as plt


count=0

x=[]

y=[]

z=[]


with open('./fruits_data.csv', 'r') as csvf:

  reader = csv.reader(csvf, delimiter=',')

  for row in reader:

    if count > 0:

      x.append(row[0])

      y.append(row[1])

      if ( row[2] == 'Apple' ): z.append('r')

      elif ( row[2] == 'Pear' ): z.append('g')

      else: z.append('y')

    count += 1


plt.figure(figsize=(11,11))


recs=[]

classes=['Apples', 'Pear', 'Bananas']

class_colours = ['r','g','y']

plt.title("Apples, Bananas and Pear by Weight and Shape", fontsize=18)


plt.xlabel("Shape category number", fontsize=14)

plt.ylabel("Weight in ounces", fontsize=14)


plt.scatter(x,y,s=600,c=z)



위 사진은 주어진 데이터를 시각화 한 것이다.

( 빨강색 : 사과 / 초록색 : 배 / 노랑색 : 바나나 )


만약 종류를 알 수 없는 과일에 대한 정보가 있을 때, 그것을 예측하는 예제 코드는 다음과 같다.


from math import pow, sqrt


dist=[]


def determineFruit(xv, yv, threshold_radius):

  for i in range(1,len(x)):

    xdif=pow(float(x[i])-xv, 2)

    ydif=pow(float(y[i])-yv, 2)

    sqrtdist = sqrt(xdif+ydif)

    if ( xdif < threshold_radius and 

         ydif < threshold_radius and sqrtdist < threshold_radius):

      dist.append(sqrtdist)

    else:

      dist.append(99)


  pear_count=0

  apple_count=0

  banana_count=0


  for i in range(1,len(dist)):

      if dist[i] < threshold_radius:

        if z[i] == 'g': pear_count += 1

        if z[i] == 'r': apple_count += 1

        if z[i] == 'y': banana_count += 1


  if ( apple_count >= pear_count and apple_count >= banana_count ):

    return "apple"

  elif ( pear_count >= apple_count and pear_count >= banana_count):

    return "pear"

  elif ( banana_count >= apple_count and banana_count >= pear_count):

    return "banana"


dist=[]

determine = determineFruit(3.5,6.2, 1)

print determine


banana




Logistic Regression (로지스틱 회귀분석)

범주형 반응변수(Y=1 or 0)의 경우, 선형 회귀분석보다 시그모이드 함수를 활용하는 로지스틱 회귀분석이 더 적합하다.

왜냐하면, 입력변수와 계수의 곱의 합으로 구성된 선형모형은 그 범위가 ±∞ 이지만, 시그모이드 함수는 (0, 1) 이기 때문이다.


아래 수식은 p개의 입력변수에 대한 Y의 확률을 시그모이드 함수로 표현한 것이다.



파이썬에서 표준 시그모이드 함수를 그려보면, 왜 이 함수를 사용하는지 조금 더 쉽게 이해할 수 있다.


import matplotlib.pyplot as plt

import numpy as np


plt.title("Sigmoid Functions vs LineSpace")


x = np.linspace(-10,10,100)


y1 = 1.0 / (1.0+np.exp(-x))

plt.plot(x,y1,'r-',lw=2)


y2 = 1.0 / (1.0+np.exp(-x/2))

plt.plot(x,y2,'g-',lw=2)


y3 = 1.0 / (1.0+np.exp(-x/10))

plt.plot(x,y3,'b-',lw=2)


plt.xlabel("x")

plt.ylabel("y")



붉은색(1) --> 초록색(1/2) --> 파랑색(1/10) 순으로 x의 계수가 낮다는 점에 주목하자.

붉은색의 경우에 값이 커짐에 따라 y가 1일 확률이 급격하게 높아지지만, 파랑색의 경우에는 경사가 완만함을 알 수 있다.

또한 값이 항상 (0, 1) 범위에 있어 해당 범주에 속할 확률로 사용이 가능함을 알 수 있다.


이제, Kaggle에서 제공한 '타이타닉 생존자 예측' 위한 데이터셋을 예제로 로지스틱 회귀분석을 적용해보자.


import numpy as np

import pandas as pd

import sklearn.linear_model as lm

import sklearn.cross_validation as cv

import matplotlib.pyplot as plt


train = pd.read_csv('./titanic_train.csv')

test = pd.read_csv('./titanic_test.csv')

train[train.columns[[2,4,5,1]]].head()


   Pclass     Sex   Age  Survived

0       3    male  22.0         0

1       1  female  38.0         1

2       3  female  26.0         1

3       1  female  35.0         1

4       3    male  35.0         0


data = train[['Sex', 'Age', 'Pclass', 'Survived']].copy()

data['Sex'] = data['Sex'] == 'female'

data = data.dropna()


data_np = data.astype(np.int32).values

X = data_np[:,:-1]

y = data_np[:,-1]


female = X[:,0] == 1

survived = y == 1


# This vector contains the age of the passengers.

age = X[:,1]


# We compute a few histograms.

bins_ = np.arange(0, 121, 5)

S = {'male': np.histogram(age[survived & ~female], 

                          bins=bins_)[0],

     'female': np.histogram(age[survived & female], 

                            bins=bins_)[0]}

D = {'male': np.histogram(age[~survived & ~female], 

                          bins=bins_)[0],

     'female': np.histogram(age[~survived & female], 

                            bins=bins_)[0]}

bins = bins_[:-1]

plt.figure(figsize=(15,8))

for i, sex, color in zip((0, 1),('male', 'female'), ('#3345d0', '#cc3dc0')):

    plt.subplot(121 + i)

    plt.bar(bins, S[sex], bottom=D[sex], color=color,

            width=5, label='Survived')

    plt.bar(bins, D[sex], color='#aaaaff', width=5, label='Died', alpha=0.4)

    plt.xlim(0, 80)

    plt.grid(None)

    

    plt.title(sex + " Survived")

    plt.xlabel("Age (years)")

    plt.legend()

    

(X_train, X_test, y_train, y_test) = cv.train_test_split(X, y, test_size=.05)

print X_train, y_train


# Logistic Regression from linear_model

logreg = lm.LogisticRegression();

logreg.fit(X_train, y_train)

y_predicted = logreg.predict(X_test)


plt.figure(figsize=(15,8));

plt.imshow(np.vstack((y_test, y_predicted)),

           interpolation='none', cmap='bone');

plt.xticks([]); plt.yticks([]);

plt.title(("Actual and predicted survival outcomes on the test set"))


logreg.coef_

array([[ 2.40922883, -0.03177726, -1.13610297]])






Support Vector Machine (서포트 벡터 머신, SVM)

SVM은 수치형 또는 범주형 반응변수(Y) 모두 적용 가능한 지도학습 알고리즘으로서, 경험적으로 좋은 성능을 제공한다고 알려져있다.

생물정보학(Bioinformatics), 문자, ㅇ므성 인식 등의 여러 범위에서 성공적인 비선형(Non-linear) 모형의 확장 알고리즘으로 자리잡고 있다.

SVM은 계산이 복잡하지 않고 구현이 쉽다는 장점이 있으나, Underfitting의 경향이 있어 정확도가 낮을 수 있다는 단점이 있다.


다음은 scikit-learn(skilearn) 라이브러리를 활용한 파이썬 예제이다.


import numpy as np

from sklearn.svm import SVR

import matplotlib.pyplot as plt


X = np.sort(5 * np.random.rand(40, 1), axis=0)

y = (np.cos(X)+np.sin(X)).ravel()

y[::5] += 3 * (0.5 - np.random.rand(8))


svr_rbfmodel = SVR(kernel='rbf', C=1e3, gamma=0.1)

svr_linear = SVR(kernel='linear', C=1e3)

svr_polynom = SVR(kernel='poly', C=1e3, degree=2)

y_rbfmodel = svr_rbfmodel.fit(X, y).predict(X)

y_linear = svr_linear.fit(X, y).predict(X)

y_polynom = svr_polynom.fit(X, y).predict(X)


plt.figure(figsize=(11,11))

plt.scatter(X, y, c='k', label='data')

plt.hold('on')

plt.plot(X, y_rbfmodel, c='g', label='RBF model')

plt.plot(X, y_linear, c='r', label='Linear model')

plt.plot(X, y_polynom, c='b', label='Polynomial model')

plt.xlabel('data')

plt.ylabel('target')

plt.title('Support Vector Regression')

plt.legend()

plt.show()





k-Means Clustering (k-평균 군집분석)

k-평균 군집분석은 데이터셋의 어떤 k 개의 영역들의 중심을 최선으로 표현할 수 있는 데이터셋의 k 개의 지점들을 찾아낸다.

이 알고리즘은 수행 전 군집의 숫자(k)를 분석가가 미리 정해주어야 한다는 단점이 있다.

그러나 k-평균 군집분석은 군집분석에 매우 많이 사용되는 방법이고, 어떤 가정도 요구하지 않는 강점을 가지고 있다.


k-평균 군집분석의 알고리즘을 간단하게 정리하면 다음과 같다.

- n개의 점 (x, y) 집합과 k개의 센트로이드 집합이 주어진다. (초기에는 랜덤하게 배정됨)

- 각 점 (x, y)에 대해, 그 지점에서 가장 가까운 센트로이드를 찾아 해당 점을 소속시킨다.

- 각 군집에서 중앙값을 찾고 이 값을 다음 k개의 센트로이드 집합으로 설정한다.

- 센트로이드 집합의 값이 변하지 않을 때까지 계속 반복한다.


다음 예제는 scikit-learn 라이브러리를 사용해 k-평균 군집분석을 구현한 파이썬 코드이다.


import matplotlib.pyplot as plt


from sklearn.cluster import KMeans


import csv


x=[]

y=[]


with open('./cluster_input.csv', 'r') as csvf:

  reader = csv.reader(csvf, delimiter=',')

  for row in reader:

      x.append(float(row[0]))

      y.append(float(row[1]))


data=[]

for i in range(0,120):

  data.append([x[i],y[i]])


plt.figure(figsize=(10,10))


plt.xlim(0,12)

plt.ylim(0,12)


plt.xlabel("X values",fontsize=14)

plt.ylabel("Y values", fontsize=14)


plt.title("Before Clustering ", fontsize=20)


plt.plot(x, y, 'k.', color='#0080ff', markersize=35, alpha=0.6)


kmeans = KMeans(init='k-means++', n_clusters=3, n_init=10)

kmeans.fit(data)


plt.figure(figsize=(10,10))


plt.xlim(0,12)

plt.ylim(0,12)


plt.xlabel("X values",fontsize=14)

plt.ylabel("Y values", fontsize=14)


plt.title("After K-Means Clustering (from scikit-learn)", fontsize=20)


plt.plot(x, y, 'k.', color='#ffaaaa', markersize=45, alpha=0.6)


# Plot the centroids as a blue X

centroids = kmeans.cluster_centers_


plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=200,

  linewidths=3, color='b', zorder=10)


plt.show()






※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 05. Financial and Statistical Models (금융과 통계 모형)


( 이전 포스팅에 이어서 .. )

An Overview of Statistical and Machine Learning (통계 및 머신러닝 개요)

머신러닝은 인간이 수행하기에 충분히 간단한 분류식들을 생성하는 것을 목표로 한다.

머신러닝은 결정 프로세스에 대한 통찰력을 제공하기 위해 인간의 추론을 충분히 모방해야만 한다.

통계와 유사하게 배경 지식은 개발 단계에서 활용될 수 있다.


통계 학습과 머신 러닝의 차이는 추론 중심이냐 예측 중심이냐의 차이라고 볼 수 있다.



#. k-최근접 이웃 (k-Nearest Neighbor)

k-NN은 훈련 데이터로부터 모델을 구축하지 않는, 알고리즘이다. 

k-NN의 접근 방법은 다음과 같다.

- 어떤 방법이든 사용해 데이터를 수집

- 거리 계산에 필요한 수치 값을 준비

- 계산된 k-NN 이웃 검색에 대한 몇 가지 작업을 수행하고, 상위 k의 가까운 이웃을 식별


from numpy import random, argsort, sqrt

from pylab import plot, show

import matplotlib.pyplot as plt


def knn_search(x, data, K) :

    ndata = data.shape[1]

    K = K if K < ndata else ndata

    # 다른 지점으로부터의 유클리드 거리

    sqd = sqrt(((data - x[:,:ndata])**2).sum(axis=0))

    idx = argsort(sqd) # 정렬

    # k-NN 인덱스 반환

    return idx[:K]


data = random.rand(2,200)   # 랜덤 데이터 셋

x = random.rand(2,1)        # 쿼리 포인트


neig_idx = knn_search(x, data, 10)


plt.figure(figsize=(12, 12))


# 데이터와 입력 포인트를 플로팅한다.

plot(data[0,:], data[1,:], 'o', x[0, 0], x[1, 0], 'o', color='#9a88a1', markersize=20)

     

# 이웃들을 하이라이팅

plot(data[0, neig_idx], data[1, neig_idx], 'o', markerfacecolor='#bbe4b4', markersize=22, markeredgewidth=1)


show()




#. 일반화 선형 모델 (Generalized Linear Models)

회귀분석은 변수들 사이의 관계를 추정하는데 쓰이는 통계 프로세스다. 구체적으로, 회귀는 독립변수 중 하나가 변화할 때 종속 변수의 전형적인 값이 어떻게 변화하는지 이해하는 데 도움이 된다.


그 중 선형 회귀분석은 보간법(interpolation)을 적용할 수 있는 고전적인 방법이나 예측력은 부족하다. 또한, 이상치와 교차 상관관계에 민감하다.

선형 회귀모형은 목표 값(y)을 입력변수(x1, x2, ... xn)의 선형결합으로 다음과 같이 추정한다.

베이즈 회귀는 분리한 추정의 일종이며, 전통적인 선형 회귀보다 더 유연하고 안정적이다.

왜 베이즈를 사용하는가? 베이즈 모델은 더 유연하고, 작은 샘플에서 더 정확하며, 이전의 정보를 포함할 수 있기 때문이다.



#. 베이즈 선형 회귀 (Bayesian Linear Regression)

먼저, 선형 회귀를 위한 그래픽 모델을 살펴보자.

주어진 값을 다음과 같이 설정한다.



목표는 이 데이터를 모델링하여 다음과 같은 함수 식을 마련하는 것이다.

여기서 w는 가중치 벡터이고, 위의 식에 나타낸 것처럼 각 Yi는 정규분포를 따르게 된다.

Yi는 랜덤변수고, 데이터로부터 랜덤변수 Yi=yi의 각 조건의 변수 x값을 바탕으로 새로운 변수 x값을 대응하는 y를 예측할 수 있다.


import numpy as np

import matplotlib.pyplot as plt

from scipy import stats


from sklearn.linear_model import BayesianRidge


np.random.seed(0)

n_samples, n_features = 200, 200


X = np.random.randn(n_samples, n_features) # 가우시안 데이터

# 정밀도 4로 가중치를 만듦

theta = 4.

w = np.zeros(n_features)


# 관심 있는 8개의 가중치만 유지

relevant_features = np.random.randint(0, n_features, 8)

for i in relevant_features :

    w[i] = stats.norm.rvs(loc=0, scale=1. / np.sqrt(theta))

    

alpha_ = 50.

noise = stats.norm.rvs(loc=0, scale=1. / np.sqrt(alpha_), size=n_samples)

y = np.dot(X, w) + noise


# 베이즈 능형 회귀 (Bayesian Ridge Regression) 에 맞춤

clf = BayesianRidge(compute_score=True)

clf.fit(X, y)


# 가중치, 예측 및 히스토그램 가중치를 시각화

plt.figure(figsize=(11, 10))

plt.title("Weights of the model", fontsize=18)

plt.plot(clf.coef_, 'b-', label="Bayesian Ridge estimate")

plt.plot(w, 'g-', label="Training Set Accuracy")

plt.xlabel("Features", fontsize=16)

plt.ylabel("Values of the weights", fontsize=16)

plt.legend(loc="best", prop=dict(size=12))


plt.figure(figsize=(11, 10))

plt.title("Histogram of the weights", fontsize=18)

plt.hist(clf.coef_, bins=n_features, log=True)

plt.plot(clf.coef_[relevant_features], 5 * np.ones(len(relevant_features)),

         'ro', label="Relevant features")

plt.ylabel("features", fontsize=16)

plt.xlabel("Values of the weights", fontsize=16)

plt.legend(loc="lower left")

plt.show()





#. 애니메이션 및 인터랙티브 플롯 작성

Bokeh, Plotly, VisPy 등의 인터랙티브한 그래프 작성 도구들이 있다.


Bokeh는 인터랙션하는 부분을 쉽게 하기 위해 자바스크립트와 D3.js로 matplotlib 객체를 시각화할 수 있으며, 큰 데이터셋에서도 좋은 성능을 제공한다.


#import bokeh

#bokeh.sampledata.download() # 이 2개 라인은 최초만 실행하면 됨


from bokeh.sampledata import us_counties, unemployment

from bokeh.plotting import figure, show, output_file

from bokeh.models import HoverTool


import collections

from collections import OrderedDict


county_coordinate_xs=[

        us_counties.data[code]['lons'] for code in us_counties.data

        if us_counties.data[code]['state'] == 'ca'

        ]

county_coordinate_ys=[

        us_counties.data[code]['lats'] for code in us_counties.data

        if us_counties.data[code]['state'] == 'ca'

        ]


colors = ["#e6f2ff", "#cce5ff", "#99cbff", "#b2d8ff", "#73abe5", "#5985b2"]

county_colors = []

for county_id in us_counties.data :

    if us_counties.data[county_id]['state'] != 'ca' :

        continue

    try :

        rate = unemployment.data[county_id]

        idx = min(int(rate/2), 5)

        county_colors.append(colors[idx])

    except KeyError :

        county_colors.append("black")


output_file("california.html", title="california.py example")


TOOLS="pan, wheel_zoom, box_zoom, reset, hover, save"

p = figure(title="California Unemployment 2009",

           width=1000, height=1000, tools=TOOLS)


p.patches(county_coordinate_xs, county_coordinate_ys,

          fill_color=county_colors, fill_alpha=0.7,

          line_color="white", line_width=0.5)


mouse_hover = p.select(dict(type=HoverTool))

mouse_hover.point_policy = "follow_mouse"

mouse_hover.tooltips = collections.OrderedDict([

        ("index", "$index"), ("(x, y)", "($x, $y)"),

        ("fill color", "$color[hex, swatch]:fill_color"),])


show(p)



Plotly는 인터랙티브한 그래프 시각화를 제공하는 또 다른 옵션이다.

그러나 참고로, 온라인상에 있어야 하고 Plotly 계정이 필요하다.


VisPy는 파이썬과 OpenGL을 사용해 만들어진 고성능 인터랙티브 도구로, 최신 GPU 성능을 제공하는 라이브러리이다.




※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 05. Financial and Statistical Models (금융과 통계 모형)


( 이전 포스팅에 이어서 .. )

확률론적 모형 (Stochastic Model)

지금까지는 임의성(Randomness)을 고려하지 않은 결정론적 모형을 살펴보았다. 지금부터는 임의성을 고려한 모형을 생각해보자.


#. 몬테카를로 시뮬레이션 (Monte Carlo Simulation)

확률 시뮬레이션으로도 불리며, 어느 예측 모형에든 위험성이나 불확실성의 영향을 활용하는 방법(기술)이다.

예측 모형에는 임의성에 대한 가정들이 포함되어 있다. 이는 포트폴리오상의 투자 수익률, 또는 작업 수행 시간에 대한 가정일 수 있다.

이렇게 임의성에 대해 모형을 세우고 미래에 투영함으로써 기대값(Expected Value)을 예측하는 것이다.


몬테카를로 시뮬레이션은 난수(Random Value)들을 입력하여 결정론적(Deterministic) 모형을 반복적(보통 100,000 ~ 수백 만 회 이상)으로 평가하는 방법이다.

모형이 복잡하고, 비선형적(Non-linear)이며 불확실한 모수(Parameter)가 하나 이상 포함하는 경우에 자주 사용된다.


결정론적 모형과의 차이점을 살펴보자. 결정론적 모형은 일관된 결과를 도출하지만, 

확률론적 모형은 확률밀도함수에서 비롯되며 도출되는 결과 또한 확률적이다.

위의 그림을 설명하면 이렇다. 우선 랜덤 입력 x1~x3에 대한 모형의 함수 f(x1,x2,x3)을 설정한 후, 여러개의 무작위 집합 {x1, x2, x3}을 생성한다.

각 입력값을 모형에 적용한 후, 평가하는 과정을 모든 값(가령 1만 개면 1만 개 까지)에 적용한다.

결과값들을 분석하고, 마지막으로 가장 가능성이 높은 것을 고른다. 몬테카를로 시뮬레이션은 난수 생성에 매우 크게 의존한다.


예를 들어, A 라는 농구 팀이 이길 확률을 알고 싶다면, 농구라는 상황에 대한 확률론적 가정 아래 수 많은 무작위 입력값들을 생성하는 몬테카를로 시뮬레이션을 통해 추정해볼 수 있겠다.

이와 같이 몬테카를로 시뮬레이션은 대다수의 현실 상황에 적용하여 문제를 해결할 수 있습니다.



#. 몬테카를로 시뮤레이션 예시 1 - 재고 관리 모형 (An Inventory Model for Monte Carlo Simulation)

한 과일 소매 판매상은 과일을 팔고 매일 주문한다. 

매 단위의 매출 당 $0.6의 이익이 발생하고, 그 날 안에 팔리지 않으면 단위당 $0.4의 손실이 발생한다.

수요 D는 [80, 140] 범위에서 균등하게 분포한다고 가정하자.

이 때, 소매상의 수익을 최대로 하기 위해서는 얼마나 주문해야 좋을까?


수익을 P, 판매량을 s, 수요를 d라고 한다면 다음과 같이 수식을 세울 수 있다.

* 만약 수요가 재고보다 많으면 수요량 만큼만 판매되며, 수요량이 재고에 못미치면 폐기된다는 전제를 하고 있는 것 같습니다.

* 즉, 의사결정의 주체인 소매상은 주문량을 결정할 수 있지만 수요량은 임의성(Randomness)이 존재함을 적용한 것입니다.


이를 바탕으로 파이썬을 통해 다음과 같이 시뮬레이션하면, 최대 기대 수익과 최적의 주문량을 구할 수 있다.

(제가 임의로 수정한 것으로, 책의 예제 코드와 다소 상이할 수 있습니다.)


import numpy as np

import matplotlib.pyplot as plt


# 수익식

def generateProfit(d):

    global s

    if d >= s:

        return 0.6*s

    else: 

        return 0.6*d - 0.4*(s-d)

    

# 시뮬레이션 시작

x = []

y = []


# 주문량 10 ~ 200 까지 시행

for s in range(10, 200):

    profit = []

    

    # n = 1,000 회 시뮬레이션 시행 // 횟수가 많을 수록 정밀해지나 거의 비슷하다.

    for i in range(1, 1000):

        

        # 균등분포(Uniform distribution)으로 정수의 수요량 난수를 생성한다.

        d = np.random.randint(low = 80, high = 140)

        # 이 수요량 난수 d에 대한 수익 계산

        profit.append(generateProfit(d))

        

    # x 축을 따라 그려질 s(주문량) 저장

    x.append(s)

    

    # y 축을 따라 그려질 평균 수익 저장

    y.append(np.mean(profit))

    

plt.grid(True)

plt.xlabel('Volume of Orders')

plt.ylabel('Average Profits')

plt.plot(x,y)


print 'Max Average Profit:', max(y)

print 'Optimal Volume of Orders:', x[y.index(max(y))]


Max Average Profit: 58.8266266266

Optimal Volume of Orders: 112



실제 계산을 통해서 시뮬레이션이 얼마나 합리적인지 확인해보자.


시뮬레이션 결과는 112로, 실제 계산값인 116과 매우 흡사하다. 난수 개수를 늘리면 더더욱 실제 계산값과 가까워진다.

* 더 복잡한 상황들과 가정을 적용했을 때, 계산보다 시뮬레이션이 용이할 수 있습니다.



#. 몬테카를로 시뮬레이션 예시 3 - 농구 게임 (A Basketball Game Model for Monte Carlo Simulation)

Khan Academy에서 Lebron James의 질문을 해결해보자.

" 3점을 뒤지고 있는 상태에서 단 30초가 남았을 때, 어려운 3점 슛을 시도하는 것이 나은가 아니면 쉬운 2점 슛과 추가 점유를 시도하는 것이 나은가? "


여기에 필요한 몇 가지 파라미터들을 다음과 같이 (쉽게 풀이하기 위해 간단히) 정의한다.

우리팀 : threePtPercent , twoPtPercent

상대팀 : oppTwoPtPercent , oppFtPercent (프리드로우 전력 퍼센티지)


상대 팀의 프리드로우 퍼센티지(oppFtPercent)가 높을 수록, 3포인트 슛이 유리하다.

반대로 oppFtPercent 값이 낮아지면? 이를 시뮬레이션해보자.


import numpy as np

import matplotlib.pyplot as plt


colors = [(31, 119, 180), (174, 199, 232), (255, 127,  14), 

          (255, 187, 120), (44, 160, 44), (214,  39,  40), (148,103,189),

          (152, 223, 138), (255,152,150), (197, 176, 213), (140, 86, 75),

          (196, 156, 148), (227,119,194), (247, 182, 210), (127,127,127),

          (199, 199, 199),(188,189, 34),(219, 219, 141), (23, 190,207),

          (158, 218, 229),(217,217,217)]


# RGB 값들을 matplotlib이 받을 수 있는 [0, 1] 범위로 스케일

for i in range(len(colors)) :

    r, g, b = colors[i]

    colors[i] = (r / 255., g / 255., b / 255.)


# 3점 시도

def attemptThree() :

    if np.random.randint(0, high=100) < threePtPercent :

        if np.random.randint(0, high=100) < overtimePercent :

            return True # 게임 승리

        return False    # 3점에 실패하거나 시간 초과로 게임 패배


# 2점 시도

def attemptTwo() :

    havePossession = True

    pointsDown = 3

    timeLeft = 30

    while (timeLeft > 0) :

            

        # 점유권을 가지고 있다면?

        if (havePossession) :

            # 우리가 3점 이상 뒤지고 있다면, 2점을 빠르게

            # 우리가 2점 이하로 뒤지고 있다면, 우리는 먼저 시간을 끌어야

            if (pointsDown >= 3) :

                timeLeft -= timeToShoot2

            else :

                timeLeft = 0

                

        # 슈팅을 해야 할까?

        if (np.random.randint(0, high=100) < twoPtPercent) :

            pointsDown -= 2

            havePossession = False

        else :

            # 상대팀이 리바운드를 한다면? 우리는 점유권을 잃는다

            # 그러나 우리가 시간을 끌게 되면, 이것은 문제가 되지 않는다.

            if (np.random.randint(0, high=100) >= offenseReboundPercent) :

                havePossession = False

            else : # 우리가 점유권을 갖지 않는 경우

                if (pointsDown > 0) : # 점유권을 되찾기 위해 파울

                    # 파울을 위한 시간

                    timeLeft -= timeToFoul

                    # 상대 팀이 두 개의 프리드로우 획득

                    if (np.random.randint(0, high=100) < oppFtPercent) :

                        pointsDown += 1

                    if (np.random.randint(0, high=100) < oppFtPercent) :

                        pointsDown += 1

                        havePossession = True

                else : 

                    if (np.random.randint(0, high=100) >= ftReboundPercent) :

                        havePossession = True

                    else :

                        # 동점 또는 이기고 있어 파울을 원하지 않음.

                        # 상대팀이 시간 끄는 것을 가정

                        if (np.random.randint(0, high=100) < oppTwoPtPercent) : 

                            pointsDown += 2 # 상대팀이 2점 기록

                        timeLeft = 0

        if (pointsDown > 0) :

            return False

        else :

            if (pointsDown < 0) :

                return True

            else :

                if (np.random.randint(0, high=100) < overtimePercent) :

                    return True

                else : 

                    return False

    

# 시각화

plt.figure(figsize=(14,14))

names=['Lebron James', 'Kyrie Irving', 'Steph Curry', 'Kyle Krover', 'Dirk Nowitzki']

threePercents = [35.4, 46.8, 44.3, 49.2, 38.0]

twoPercents =   [53.6, 49.1, 52.8, 47.0, 48.6]

colind=0


for i in range(5) : # 각각 수행할 수 있음

    x=[]

    y1=[]

    y2=[]

    trials = 400 # 시뮬레이션 실행 시도 수

    threePtPercent = threePercents[i]   # 3점 슛 만들 기회 %

    twoPtPercent = twoPercents[i]       # 2점 슛 만들 기회 %

    oppTwoPtPercent = 40                # 상대팀이 2점 슛 만들 기회 %

    oppFtPercent = 70                      # 상대팀의 프리드로우 %

    timeToShoot2 = 5                       # 2점 슛을 위해 경과된 초

    timeToFoul = 5                          # 상대팀을 파울하는 데 경과된 초

    offenseReboundPercent = 25        # 공격 리바운드 %

    ftReboundPercent = 15                # FT를 놓친 후 공격 리바운드 %

    overtimePercent = 50                  # 연장선에서 우승 확률 %

    

    winsTakingThree = 0

    lossTakingThree = 0

    winsTakingTwo = 0

    lossTakingTwo = 0

    curTrial = 1

    

    while curTrial < trials :

        # 3점 획득 시도 실행

        if (attemptThree()) :

            winsTakingThree += 1

        else :

            lossTakingThree += 1

        

        # 2점 획득 시도 실행

        if attemptTwo() == True :

            winsTakingTwo += 1

        else :

            lossTakingTwo += 1

        

        x.append(curTrial)

        y1.append(winsTakingThree)

        y2.append(winsTakingTwo)

        curTrial += 1

    

    plt.plot(x, y1, color=colors[colind], label=names[i]+" Wins Taking Three Point", linewidth=2)

    plt.plot(x, y2, color=colors[20], label=names[i]+" Wins Taking Two Point", linewidth=1.2)

    colind += 2

    

legend = plt.legend(loc='upper left', shadow=True,)

for legobj in legend.legendHandles :

    legobj.set_linewidth(2.6)

    

plt.show()



모든 경우에서 상대 팀의 프리드로우 비율이 높기 때문에(70%), 모든 선수들에 대해 몬테카를로 시뮬레이션은 3점 득점을 제안하고 있다.



#. 변동성 그래프 (The Volatility Plot)

표준편차는 평균 주위에서의 변화량 또는 흩어짐 정도를 측정하는 통계 용어로 변동성의 척도이다.

이처럼 정의에 의해, 흩어짐의 정도란 실제 값과 평균 값 사이의 차이이다.

가까운 값들을 바탕으로 변동성을 그래프로 살펴보기 위해 주어진 시작 일로부터 어떻게 볼 수 있는지,

어떻게 특정 주식에 대해 수행하는지 예제(IBM, 2005.10.01. ~)로 살펴보자.


import pandas_datareader as stockdata

import numpy as np


ibmquotes = stockdata.DataReader(name='IBM', data_source='yahoo', start='2005-10-01')


ibmquotes['Volatility'] = np.log(ibmquotes['Close'] / ibmquotes['Close'].shift(1))


ibmquotes[['Close', 'Volatility']].plot(figsize=(12,10),subplots=True)



주가 변동성은 다양한 특징적 피크점을 가질 수 있는 가격의 변동이다.

지수(exponential) 함수는 시간에 따른 성장을 보여주고,

로그(log, 지수의 역) 함수는 성장에 이르기 위한 시간을 측정할 수 있게 한다.





※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 05. Financial and Statistical Models (금융과 통계 모형)


금융과 경제 모형들은 확률과 통계를 사용하며 데이터의 단순화와 추상화를 돕는다.

모형에 대해서 논하기 전에, 데이터를 살피는 것은 항상 중요하다는 사실을 잊지 말자.
즉, 데이터 분석의 첫 단계에서는 반드시 데이터를 시각화 해보는 일이 필요하다.
불량 데이터, 아웃라이어, 결측치 등과 같은 문제들은 데이터 시각화를 통해 쉽게 검출할 수 있기 때문이다.
이들은 가능하면 모두 정정하거나 삭제해야 마땅하나, 주식 시장과 같이 특별한 경우에는 아웃라이어가 큰 의미를 지닌 경우도 있다는 점에 유의하자.

이 장에서는 몇 가지 모형의 예제들을 살펴볼 것이다. 이 외에도 유용한 애플리케이션이 많이 존재한다.

그 전에, 기본적인 금융 문제를 파이썬으로 시각화하여 해결하는 방법을 간단한 예시를 통해 알아보자.

결정론적 모형 (Deterministic Model)

투자의 궁극적 목적은 수익을 내는 것이며, 투자의 손익은 가격의 변동과 보유한 자산 수에 달려 있다.


#. 총 수익률

- 시간(현재 시점) t에 투자 양을 Pt라고 가정하면, 총 수익률 Rt를 다음과 같이 간단하게 표현할 수 있다.

   즉, Pt = 10, P_t+1 = 10 이라면, R_t+1 = 0.06 = 6% 이다.


- 더 나아가, 최근 k년 동안의 수익률은 다음 식과 같이 1년 수익률(t-k부터 t까지)의 곱이다.


- Rt에 해당하는 인플레이션을 Ft라 정의하면, 위 식을 다음과 같이 정리할 수 있다.

   즉, 인플레이션을 고려하지 않으면(Ft = 0) 직전 식과 같아진다.


- 또한, 배당금과 같은 추가적인 수익이 있다면 다음과 같이 수익률을 정리할 수 있다.


#. 파이썬으로 위 수식을 적용해 문제를 풀어보자.

- 2010년 초기에 $10,000를 투자했고 수익률이 6%라면, 몇 년이 지나야 투자금액의 2배($20,000)가 될까?

(단, 인플레이션과 다른 수익은 고려하지 않는다. --> Ft = Dt = 0)

- 저는 2배가 되는 시점을 시각적으로 쉽게 찾기 위해, 'y = 20,000' 직선을 추가하여 교차하는 지점을 확인해봤습니다.

(참고로, 책에서는 y = 2x 그래프? 를 그리라고 했습니다.)

import matplotlib.pyplot as plt


principle_value = 10000 # 투자 금액

grossReturn = 1.06       # Rt


return_amt = []

x = []

year = 2010

return_amt.append(principle_value)

x.append(year)


for i in range(1,15):

    return_amt.append(return_amt[i-1] * grossReturn)

    print 'Year-', i, ' Returned:', return_amt[i]

    

    year += 1

    x.append(year)

    

# 눈금이 보이도록

plt.grid()


# return값들의 커브 그리기

plt.plot(x, return_amt, color='r')

plt.plot(x, [20000]*len(x), color='b')


   약 2022년 즈음에 목표 수익($20,000)을 달성할 수 있을 것으로 기대할 수 있다.


#. 모기지론의 적용

- 금융기관에서 $350,000를 연 5% 이자율로 30년 만기 원리금균등상환으로 대출받았을 때, 월 상환금은 다음과 같이 계산될 수 있습니다.

(책의 내용과 조금 다를 수 있습니다. 읽으면서 제가 다시 정리한 것으로, 오류 발견 시 댓글로 알려주시면 감사하겠습니다!)


   P : 원금, r : 이자율(%), 기간 : t(월)


- 1,878$를 360개월동안 납입하면 총 납입원금은 $676,080가 됩니다. 즉, $350,000를 빌렸지만 실질적으로 빌린 돈이 2배가 되는 셈이지요.

- 이는 원금에 이자가 복리로 붙기 때문인데, 월 상환금을 높이면 총 납입원금도 줄고 조기 상환도 가능합니다.

- 문제를 파이썬으로 시각화 해보면, 상환금을 100$ 올릴 때마다 얼마가 절약되며 얼만큼 조기에 상환이 가능한지 쉽게 확인할 수 있습니다.

(예제 코드는 책의 출판사 사이트에서 받으실 수 있습니다.)



- 산점도(Scatter Plot)와 버블차트를 조합, 대출금과 추가상환액에 따라 절약되는 금액을 다음과 같이 파이썬으로 시각화 할 수 있다.




( .. 다음 포스팅에 계속 .. )



※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 04-2. Interactive Plotting (반응형 시각화)


( 이전 포스팅에 이어서 .. )

이 책에서는 주로 matplotlib 이라는 파이썬 패키지로 시각화를 진행하고 있습니다.

워드 클라우드(Word Cloud) 예제

주어진 문장에서 자주 나타나는 단어에 대한 중요성을 보여주는 시각화이다.
다른 말로, 태그 클라우드(Tag Cloud)나 단어 비중의 시각화라 불린다.

워드 클라우드는 소셜 미디어와 마케팅 분야에 유용하게 사용되고 있다.
- 소비자들의 브랜드에 대한 인식 분석
- 어떤 단어들과 테마가 Target 시장에서 경쟁력을 가지는지 확인


#. wordcloud 라이브러리 설치


Mac 기준으로 작성된 책이여서, Windows OS 환경에서의 설치는 다음과 같이 제가 했던 방식으로 진행하시면 될 것 같습니다.


(1). 아나콘다 프롬포트 실행



(2). conda install -c conda-forge wordcloud 입력

중간에 Proceed ([y]/n)? 나오면 y 입력




#. 워드 클라우드 생성


원본 데이터(wordcloudInput_fromFeeds.txt)와 폰트 파일(RemachineScript.ttf) 파일은 책의 예제 다운로드를 통해서 얻으실 수 있습니다.


from wordcloud import WordCloud, STOPWORDS

import matplotlib.pyplot as plt

from os import path


d = path.dirname("__file__")

text = open(path.join(d, 'wordcloudInput_fromFeeds.txt')).read()


wordcloud = WordCloud(

        font_path='remachine_script/RemachineScript.ttf',

        stopwords=STOPWORDS,

        background_color='#222222',

        width=1000,

        height=800).generate(text)


plt.figure(figsize=(13,13))

plt.imshow(wordcloud)

plt.axis('off')

plt.show()



#. 텍스트 감성 분석

고전적인 방법은 아래의 수식을 활용하는 것이다. 또는 TextBlob 패키지를 이용하는 방법이 있다. 추후에 더 자세하게 다루도록 한다.




주식 차트 시각화 예제

blockspring 라이브러리를 통해 반응형 시각화가 가능하다.

자동으로 생성된 결과물은 HTML 코드와 자바스크립트(D3.js) 포맷으로 되어 있다.


* 위에서 실행한 아나콘다 프롬포트에서 " pip install blockspring " 명령을 입력하시면 블락스프링 패키지를 이용할 수 있습니다.


import blockspring 

import json  


print blockspring.runParsed("stock-price-comparison", 

   { "tickers": "FB, LNKD, TWTR", 

   "start_date": "2014-01-01", "end_date": "2015-01-01" }).params




스포츠 데이터 시각화 예제

이 외에도 다음과 같은 결과물을 파이썬을 통해 얻을 수 있다.





이번 장에서는 간단한 동작 예제만 살폈으며, 추후 좀 더 많은 예제들을 살펴보게 될 것이다.



※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 04-1. Numerical Computing (수치 연산)


NumPy, SciPy 라이브러리

이들은 파이썬 계산 모듈로서, 함수들이 미리 컴파일 되어있어 빠르게 수행된다.

NumPy는 많은 양의 수치 데이터를 다루기 위한 것이며, SciPy는 응용 수학 부문의 유용한 알고리즘을 제공하는 NumPy의 확장판이다.


#. Interpolation (보간)

- NumPy의 interp() 함수


#. Vectorization 기능

- NumPy와 SciPy에서 vectorize()는 함수를 벡터화하여 효율적인 작업을 가능하게 한다.

- 즉, vectorize()는 스칼라 값을 인수로 받는 함수를 배열도 인수로 사용되도록 하는 기능이다.


#. NumPy 선형 대수

- dot(a,b) : 두 배열의 내적

- linspace(a,b,n) : a부터 b의 범위에서 n개의 수를 생성

- diff(x) : 미분


- linalg.norm(x) : 행렬이나 벡터의 노말

- linalg.cond(x) : 조건 수

- linalg.solve(A, b) : Ax=b의 솔루션

- linalg.inv(A) : 역행렬

- linalg.pinv(A) : 역행렬

- linalg.eig(A) : 제곱의 고유/벡터값

- linalg.eigval(A) : 고유값

- linalg.svd(A) : 단수 값 분해


#. SciPy의 함수

- spio.loadmat : 행렬 로드

- spio.savemat : 행렬 저장

- scio.imread : 이미지 로드

- scipy.polyid : 다항식을 정의하여 여러 편리한 계산이 가능하도록 도움.

* 등 많은 것이 이미 SciPy에 구현되어 있으므로, 파이썬으로 계산 프로그램을 개발할 때 의도한 기능 관련하여 먼저 개발 문서를 확인해보자.


- scipy.cluster : 벡터 양자화, K-means 등 클러스터링

- scipy.fftpack : 고속 푸리에 변환

- scipy.integrate : trapezoidal(사다리꼴), Simpson's, Romberg 등의 방법으로 적분 수행.

quad, dblquad, tplquad 함수로 객체에 싱글, 더블, 트리플 통합 수행 가능.

- scipy.interpolate : 분리된 수치 데이터와 선형 또는 spline interpolation(보간) 개체 함수와 클래스

- scipy.linalg : NumPy의 linalg 패키지를 위한 wrapper. 모든 NumPy 함수들은 scipy.linalg의 일부임.

- scipy.optimize : Neider-Mead Simplex, Powell, 결합 그라데이션 BFGS, 최소 제곱, 제약 최적화, 시뮬레이션 annealing, Newton's Method, 이분법, Broyden Anderson, Linear Search 등을 통한 최대값과 최소값 등을 찾는 기능.

- scipy.sparse : Sparse matrices 관련

- scipy.special : 타원, 베셀, 감마, 베타 초기화, 포물선, 실린더, Mathieu 및 회전 타원체 파도와 같은 계산 물리 위한 특수 함수



MKL 함수

인텔이 개발한 벡터와 행렬에 대한 고성능 처리를 지원하는 함수이다.

FFT 함수와 벡터 통계 함수도 포함되어있다.

인텔 프로세서(CPU)에서 효율적으로 동작하도록 최적화 되어있다.

아나콘다 사용자들은 아나콘다 가속 패키지 일부의 애드온으로 이용 가능하다.




파이썬의 성능 이슈

종종 파이썬의 성능 이슈로 인해 C 언어로 프로그램을 다시 작성하거나, 컴파일된 C 함수들을 호출하는 일이 있다.

Cython처럼 더 쉽게 최적화를 하기 위한 목적의 많은 프로젝트들이 있으나, 기존 파이썬 코드를 효율적으로(빠르게) 만드는 것이 좋다.


#. Numbapro

- 파이썬 코드를 CUDA 가능 CPUs나 멀티코어 CPU, 또는 GPU에서 수행하도록 만드는 Continuum Analytics의 파이썬 컴파일러이다.

- 런타임에 just-in-time(JIT) 컴파일 된다.

- 상업 라이센스임에 유의


#. Scipy.weave

- C 코드를 중간에 삽입, NumPy 배열을 C 층으로 자연스럽게 이동시켜주는 모듈. 효율적인 메크로를 가지고 있다.


#. 멀티코어 활용


#. 프로세스 Pool 활용

- Pool은 멀티프로세싱의 패키지에 또 다른 클래스이다.

- Pool 안에 생성도니 프로세스 수를 정의할 수 있으며 각 프로세스에게 전달될 파라미터를 가지고 있는 반복 객체를 보낼 수 있다.


#. Disco 등 분산 계산 패키지 활용

- MapReduce 패러다임 기반 가벼운 오픈소스 프레임워크

- 이 외 Hadoop Streaming, mrjob, dumbo, hadoopy, pydoop 등이 있다.



분할(Slicing)

배열은 리스트나 튜플로 분할될 수 있다.

[ : , : , ... : ] 와 같은 문법을 사용한다.


#. :and:    ==    0:n:0

#. m: , m:n:    ==    m:n:1

#. :n:    ==    0:n:1

#. ::d:    ==    0:n:d


#. 예시


>>> x = numpy.array([5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])


>>> x[:2] # 0 ~ 2 까지

array([5, 6])


>>> x[::2] # 0 ~ n 까지 2 스탭

array([5, 7, 9, 11, 13, 15, 17, 19])



#. 행렬의 분할


>>> a = numpy.array([ [4,5,6], [7,8,9], [1,2,3] ])

>>> a

array([[4, 5, 6],

       [7, 8, 9],

       [1, 2, 3]])


>>> a.flat[:]

array([4, 5, 6, 7, 8, 9, 1, 2, 3])



색인(Indexing)

#. 수치 색인
- 정수 데이터를 가진 리스트로 Indexing 할 수 있다.

>>> a = 10 * numpy.arange(5.0)

>>> a

array([0., 10., 20., 30., 40.])


>>> a[1] # 값을 반환

10.0

>>> a[[1]] # 배열을 반환

array([10.])


>>> sel = numpy.array([3,1,4,2,3,3])

>>> a[sel] # 위치를 반복하여 배열로 반환할 수 있다

array([ 30.,  10.,  40.,  20.,  30.,  30.])


>>> sel = numpy.array([[4,1], [3,2]])

>>> sel # 2차원에서도 가능

array([[4, 1],

       [3, 2]])

>>> a[sel]

array([[ 40.,  10.],

       [ 30.,  20.]])



#. 논리 색인

- 전등 스위치와 같이, 참이거나 거짓인 조건을 활용할 수 있다.


>>> x = numpy.arange(-4, 5)

>>> x

array([-4, -3, -2, -1,  0,  1,  2,  3,  4])


>>> x < 0

array([ True,  True,  True,  True, False, False, False, False, False], dtype=bool)


>>> x[x>0]

array([1, 2, 3, 4])


>>> x[abs(x) >= 2]

array([-4, -3, -2,  2,  3,  4])


>>> x = numpy.reshape(numpy.arange(-8, 8), (4, 4)) # 2차원 예시

>>> x

array([[-8, -7, -6, -5],

       [-4, -3, -2, -1],

       [ 0,  1,  2,  3],

       [ 4,  5,  6,  7]])


>>> x[x<0]

array([-8, -7, -6, -5, -4, -3, -2, -1])


>>> from math import isnan # 여러 방식의 논리 색인


>>> list1 = [[3, 4, float('NaN')],

                 [5, 9, 8],

           [3, 3, 2],

                 [9, -1, float('NaN')]]


>>> [elem for elem in list1

if not any([isnan(element) for element in elem])]

[[5, 9, 8], [3, 3, 2]]


>>> list2 = [3,4,5,6]


>>> [list2[index] for index, elem in enumerate(list1)

     if not any([isnan(element) for element in elem])]

[4, 5]



파이썬의 다양한 데이터 구조

파이썬은 스택, 리스트, 집합(Set), 시퀀스, 튜플, 리스트, 힙, 배열, 사전(Dictionary), 디큐(Dequeue) 등의 데이터 구조를 가진다.

참고로, 튜플은 불변성으로 리스트보다 더 효율적인 메모리 효율을 갖는다.



#. 스택(Stack)

- list() 함수는 스택으로서 사용되기 유용하다.

- 새로 들오온 요소는 뒤로 추가되고, 가장 먼저 들어온 것이 먼저 나가는(선입선출) 실행 원칙을 가진 추상 데이터 유형이다.


- append()로 아이템을 추가한다.

- pop()으로 아이템을 추출한다.

- remove(item-value)로 아이템을 제거한다.



#. 튜플(Tuple)

- 불변하는 오브젝트의 시퀀스이다. 따라서 오브젝트를 바꿀 수도, 제거할 수도 없다. 하지만 튜플 자체(오브젝트 전체)를 지우는 것은 가능하다.

- 다원화된 데이터 구조를 갖는다.

- 리스트가 같은 요소들의 시퀀스인 반면, 튜플은 요소들이 서로 다른 의미를 가진다.

- 리스트는 시퀀스를 갖고, 튜플은 구조를 갖는다.

- 튜플의 예는 한 주의 요일, 강의의 과목 이름, 등급 척도 등이다.


- del tuble-name 으로 튜플을 지운다.

- cmp(tup1, tup2) : 튜플의 요소를 비교

- len(tuple) : 전체 길이

- max(tuple) : 요소들의 최댓값

- min(tuple) : 요소들의 최솟값

- tuple(lista) : 리스트를 튜플로 변환


- 참고로, 파이썬은 max() 함수에 문자열의 리스트를 입력하면 가장 긴 문자열을 return한다. (min() 함수도 마찬가지)


#. 셋(Set)

- 리스트와 유사하나, 순서가 없는 집합이다. 리스트는 위치나 색인에 의해 순서화된다.

- 중복을 허용하지 않는다. (중복이 없다)


#. 사전(Dictionary)

- 키와 값의 쌍으로 구성된, 순서가 없는 데이터 값들의 집합

- 색인으로서 키를 기반으로 값에 접근할 수 있는 장점이 있다.

- 디폴트 사전(Default Dictionary)은 키와 값의 쌍이 삽입된 순서를 유지하지 않는다. OrderedDict() 함수로 생성된 빈 사전은 순서를 유지한다.


>>> # 예제 1 : 아프리카의 10대 GDP

>>> gdp_dict = {

        'South Africa': 285.4,

        'Egypt': 188.4,

        'Nigeria': 173,

        'Algeria': 140.6,

        'Morocco': 91.4,

        'Angola': 75.5,

        'Libya': 62.3,

        'Tunisia': 39.6,

        'Kenya': 29.4,

        'Ethiopia': 28.5,

        'Ghana': 26.2,

        'cameron': 22.2

        }


>>> gdp_dict['Angola']

75.5



( .. 다음 포스팅에 계속 .. )



※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 03. Getting Started with the Python IDE (파이썬 IDE로 시작하기)


이 책에 따르면, 이미 파이썬 2.7 버전대에서 작성된 여러 라이브러리들이 3.x 버전대와 호환이 잘 되지 않는다고 하니 2.7 버전대를 사용하기로 합니다.


또한, 이 책으로 공부를 하시는 분들이라면 아나콘다(Anaconda)를 설치하시는 것이 편리할 것입니다.

나중에 설치 과정을 정리해보겠습니다.



파이썬의 강점


방대하고, 유용한 라이브러리들을 쉽게 설치하여 적용할 수 있다는 것이 파이썬의 가장 큰 강점이다.

GUI를 만들 수 있고, DB와 연결할 수 있으며, 랜덤 수를 생성하여 시뮬레이션을 시행할 수 있고, 수학적 연산에서의 높은 정밀도를 가진다.

2D, 3D 그래픽 시각화, 머신 러닝과 통계적 알고리즘 등을 수행할 수 있는 고성능의 패키지들도 배포되고 있다.



아나콘다 (Anaconda)


Continuum Analytics가 개발한 아나콘다는 데이터 분석과 시각화를 위해 가장 많이 사용되는 IDE 중 하나로 잘 알려져 있다.

* IDE란, 통합개발환경(Integrated Development Environment)으로서 편리하게 어플리케이션을 개발할 수 있도록 여러 기능들을 모아둔 것입니다.


아나콘다는 개발자가 필요한 파이썬 라이브러리를 쉽게 설치하고 업데이트 할 수 있도록 돕는다.
빅 데이터의 관리, 분석 그리고 비즈니스 인텔리전스를 위한 시각화, 과학적 분석, 엔지니어링, 머신 러닝 등 강력한 파이썬 패키지들의 집합이다.

아나콘다는 IPython과 Spyder 등의 IDE를 포함한다.
* 개인적으로 저처럼 기존에 R을 사용하셨던 통계 전공자분들에게 Spyder를 추천합니다. RStudio와 환경이 비슷한 것 같아 큰 이질감이 없습니다.


추천하는 파이썬 시각화 패키지들


#. matplotlib

- 가장 많이 사용되는 파이썬 시각화 라이브러리

- NumPy, SciPy와 연결되어 있음

- 과학 분야 파이썬 커뮤니티에서 주로 사용되고 있다


#. Plotly

- 시각화와 분석을 함께 할 수 있도록 브라우저에서 작동하는 플랫폼

- 반응적으로 그래프 작업을 할 수 있고, 스타일을 입힐 수 있다.

- matplotlib 기반으로 작성된 시각화 코드를 Plotly 버전으로 쉽게 고칠 수 있다


#. Veusz

- 파이썬과 PyQt로 만어졌으며 GPL-scientific 시각화 라이브러리


#. Mayavi

- 3차원 시각화 패키지


#. NetworkX

- 복잡한 네트워크를 생성하며 가공하고 그 구조와 역학, 기능 연구에 사용


#. pygooglechart

- 구글 시각화 API와 연동할 수 있게 돕는 라이브러리



반응형(interactive) 시각화 패키지들


#. Bokeh

- 아웃 포커스된 이미지의 일부분 혹은 블러링을 묘사하는 일본어에서 유래

- 예시 : http://nbviewer.jupyter.org/gist/fonnesbeck/ad091b81bffda28fd657


#. VisPy

- OpenGL 활용, 고성능 반응형 시각화 라이브러리

- 예시 : http://vispy.org/gallery.html



※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 02. Data Analysis and Visualization (데이터 분석과 시각화)


Storytelling 방식의 데이터 시각화


#. 데이터를 이용해 즐거운 이야기를 만들자

- 올바른 방법으로 표현된 데이터는 이해하고 기억하기 쉽기 때문이다

- 좋은 시각화를 만들기 위해 첫 번째로 해야 할 가장 중요한 일은 '최종 목표'를 명확히 설정하는 것이다.


#. 시각화는 독자의 입장에서

- 단지 저자(데이터를 시각화하는 주체)의 입장에서 데이터를 시각화하면, 그 의의가 저자에 의해 결정되어 단순 정보 전달에 그칠 수 있다.

- 그러나 독자 중심으로 생각하면, 독자와 저자는 상호 교류하며 서로가 데이터를 유연하게 고르고, 분석하고, 시각화된 데이터를 이해할 수 있게 된다.


#. 매력적인 스토리텔러가 되어야

- Storyteller들은 대화에 있어 독자에 대한 이해가 중요하다는 것을 명확히 알고 있다.

- 데이터의 스토리라인 또한 청중에 따라서 표현과 전달 방식이 달라야 한다.


#. 올바른 시각화 방법을 선정하자

- 비교와 순위

** 특히, 비교는 분석 타겟의 특성을 더 강조할 수 있을 뿐 아니라, 그것을 주장할 수 있는 근거를 만들어주기 때문에 중요하다고 생각합니다.

- 상호 연관성

: 산점도(산포도), 상관관계, 히트맵

- 분포

: 히스토그램, 박스플랏(상자 그래프), 상자 수염 그래프(Box and Whisker plot)

* 분포는 특히 이상점을 찾는데 유용하게 사용될 수 있습니다.

- 지역적 특성이나 정보

: 지도 위에 도형의 크기와 색을 활용

- 부분에서 전체의 관계

: 파이 차트(원 그래프), 그룹 막대 그래프, 누적 열 차트

- 시간 경과에 따른 경향

: 막대 그래프, 시계열 그래프, 추세선



반응형(interactive) 시각화


#. 반응형 시각화의 장단점

- 많은 양의 정보를 하나의 플랫폼을 통해 전달 가능하다

- 그러나 모든 시각화 가능성에 대해 확인해봐야 하므로 사용자에게 많은 시간을 요구하게 된다.


#. 이벤트 리스너

- 사용자의 요구(query, needs)는 프로그래밍적으로 이벤트 리스너를 통해 실시간으로 처리(catch)해야 한다.

- 반응형 시각화에서는, 주로 마우스의 움직임이나 클릭 등을 인식하는데 사용한다.


#. 몇 가지 원칙

- 사용자의 행동이 시스템에 반영됐다는 것을 명확히 인식시켜줘야 함 (ex: 강조 표시, 밑줄, 색 변화, 굵게, 기울임 등)

- 피드백은 평균 1초 내에 구현되도록 해야 답답함을 느끼지 않을 것이다.

- 만약 알고리즘 특성 때문에 결과를 표시하기까지 시간이 필요할 경우, loading과 같은 처리 중 표시를 해야 이탈을 방지할 수 있다.



데이터 시각화는 예술이자 과학이며, 수학적인 문제를 푸는 일


#. 데이터 시각화의 목적을 수시로 상기하자

- 시각화는 사용자, 독자, 청자에게 시각적인 방법으로 정보를 명확하고 효과적으로 전달하고 소통하는 것

- 효과적인 시각화 결과물은 데이터와 증거들에 대해 분석하고 추론할 수 있게 돕는다.

- 또한 복잡한 데이터를 쉽게 접근 가능토록 하고, 이해시키며, 사용할 수 있게 돕는다.

- 비교와 특이점을 이해하는 것과 같은 특정한 분석이 중요할 수 있고, 이를 그림으로 표현할 수 있다면 더욱 좋다.


#. 효과적인 방법을 사용하자

- 수학적 문제를 푸는 것 처럼, 분석 목표를 달성하는 데에는 유일한 한 가지 방법만이 있는 것은 아니다.

- 표는 데이터의 날 것을 보여주지만, 다양한 형태의 도표와 차트는 변수들 간의 관계와 패턴 등을 잘 표현할 수 있다.




+ Recent posts