일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 하이퍼레저 패브릭
- 파이썬 머신러닝
- 엔터프라이즈 블록체인
- Hyperledger fabric gossip protocol
- CORDA
- 파이썬 데이터분석
- hyperledger fabric
- akka 강좌
- 주키퍼
- play 강좌
- Golang
- 하이브리드앱
- 파이썬 동시성
- 스칼라 동시성
- 스칼라 강좌
- 파이썬
- 스칼라
- 파이썬 강좌
- Play2
- Actor
- Akka
- 블록체인
- 스위프트
- 안드로이드 웹뷰
- Play2 로 웹 개발
- 그라파나
- 이더리움
- play2 강좌
- 플레이프레임워크
- Adapter 패턴
- Today
- Total
HAMA 블로그
파이썬 코딩으로 말하는 데이터 분석 - 5. 데이터 다루기 (기본,척도조절,차원축소) 본문
파이썬 코딩으로 말하는 데이터 분석 - 5. 데이터 다루기 (기본,척도조절,차원축소)
[하마] 이승현 (wowlsh93@gmail.com) 2017. 1. 22. 13:04순서
1. 통계 - 카운팅,min,max,평균,중앙값,산포도,분산,편차,공분산,상관관계
2. 가설과 추론 (베이지언 - 사후확률,우도)
3. 군집화 (K-Means)
4. 연관 (Apriori)
5. 함수형으로 데이터 다루기
6. 경사하강법
7. 회귀분석
8. 은닉 마코프법 (HMM)
9. k-NN
10. DTW
* 참고로 "밑바닥부터 배우는 데이터과학" 서적은 numpy,scikit-learn 등의 외부라이브러리를 활용은 배제되었습니다.
데이터 다루기
대부분의 언어들이 함수형을 차용하고 있으며 , 파이썬도 빠질리는 없다. 파이썬의 함수형 도구들을 사용하여 데이 터 분석을 해보자.
참고:
파이썬, C++ ,Java 8은 모두 기본적으로는 객체지향언어에 가깝지만 모두 함수형 파라다임을 차용하고 있다. 스칼라 같은 언어는 함수형 하이브리드언어라고 볼 수 있으며, 클로저는 거의 함수형언어라고 본다. 함수형언어는 불변(부수효과가 없는)을 지향하고 있다. 이 말인 즉 객체지향이 어떠한 객체를 상정해두고 그 객체안의 메소드를 이용하고 속성들을 변화시키면서 진행되는 반면 함수형 언어는 여러 순수함수들을 통과하면서 목적을 이루기위해 진행된다. 순수함수는 항상 x 를 대입하면 y 를 내뱉는것을 확신시켜준다.
주요 도구: List comprehension
함수형 (고차함수) 의 특징인 lambda , filter, map, reduce 알고리즘을 리스트로 간단히 구현하는 방법입니다.
예를 들면
a = [1,2,3,4,5] 중에서 홀수만 골라낸다고 할때
람다식을 이용하면 아래와 같이 됩니다.
filter (lambda x : x % 2 , a)
근데 이것을 List comprehension 으로 표현하면
[x for x in a if x % 2]
이렇게 됩니다. 즉 a 라는 컬렉션에서 하나씩 값(x) 을 가져와서 , 만약 짝수면 리스트의 요소로 추가합니다.
파이썬에서는 좀 황당한게 List comprehension 이 더 사용성 (가독성) 이 좋아서 오래전 부터 고차함수들을 제꼈(?)습니다. @@
collection.Counter 란?
c = Counter("문재인","문재인","안희정","안희정","안철수","이재명","이재명","이재명","이재명")
c["문재인"] 은 2 가 되며 , c["안철수"] 는 1 , c["이재명"] 는 4 이 되는
결국 키는 요소가 되며 value 는 그 요소의 갯수를 자동으로 누적해서 가지고 있다.
c.most_common(2) 를 통해 가장 많이 누적된 상위 2개를 알 수 도 있는 굉장히 편리한 컬렉션 클래스이다
코드로 말해요.
@ 아래와 같은 주식 데이터가 있다고 하자. / 종가 / 날짜 / 심볼로 이루어져있다.
data = [ {'closing_price' : 102.06,
'date' : datetime.datetime(2014, 8, 29, 0, 0),
'symbol' : 'AAPL'}, ...
...
* 파일에 저장된 모습 (아래 다운로드 받을 수 있다)
symbol date closing_price
AAPL 2015-01-23 112.98
AAPL 2015-01-22 112.4
AAPL 2015-01-21 109.55
AAPL 2015-01-20 108.72
AAPL 2015-01-16 105.99
AAPL 2015-01-15 106.82
AAPL 2015-01-14 109.8
..
@ 심볼이 'AAPL' 인 것들 중에서 가장 높은 가격 산출
max_aapl_price = max(row["closing_price"]
for row in data if row["symbol"] == "AAPL")
print "max aapl price", max_aapl_price
data 컬렉션에서 값(row) 을 하나 가져와서 심볼이 "AAPL" 인것들 중에서 값이 가장 높은것
@ 심볼별로 데이터 그룹화
# group rows by symbol
by_symbol = defaultdict(list)
for row in data:
by_symbol[row["symbol"]].append(row)
심볼이 같은것 끼리 묶어 줍니다. 즉 { "AAPL" : [ ... , ... ] , "BBPL" : [ ..., ... ] .......} 이런식으로요~
defaultdict 은 파이썬에서 제공하는 컬렉션 중에 하나로써 , 만약 키 값이 없더라도 새로 생성해서 append 하게 해 줍니다. 일반 딕셔너리로 저렇게 코딩하면 에러죠.
@ 그룹별 가장 높은 가격
max_price_by_symbol = {symbol: max(row["closing_price"] for row in grouped_rows)
for symbol, grouped_rows in by_symbol.iteritems()}
위에서 심볼별 리스트들을 가져와서 각각에 대한 가장 높은 값을 구해줍니다.
결과는 {'AAPL': 119.0, 'FB': 38.23, 'MSFT': 22.78}
@ 특정필드를 리스트로 추출
def picker(field_name):
return lambda row: row[field_name]
def pluck(field_name, rows):
return map(picker(field_name), rows)
picker 는 특정 필드의 값을 리턴해주는 함수를 반환합니다.
pluck 는 rows 들 중 특정 필드의 값 만으로 리스트를 만들어 줍니다.
즉 field_name 에 "closing_price" 를 입력해주면 , 그 값들로만 이루어진 리스트를 리턴함.
@ 데이터를 그룹화시켜서 모으고 , value_transform 공식에 의해서 변경시킨다.
def group_by(grouper, rows, value_transform=None):
grouped = defaultdict(list)
for row in rows:
grouped[grouper(row)].append(row)
if value_transform is None:
return grouped
else:
return {key: value_transform(rows)
for key, rows in grouped.iteritems()}
심볼이라든지 어떤 특정 것을 구분하여 그룹화시키고 , 각 그룹을 value_transform 에 의해 계산합니다.
value_transform 가 그룹의 max 값을 찾는 것이라면 {"AAPL" : 1030 , "BBPL" : 2000 ..} 뭐 이런식으로 결과가 나오겠지요.
@ 그룹된 로우를 date 에 의해 정렬한 후에 이전날과 비교한 오늘의 종가의 증감비율을 추가한다.
위에 언급한 value_tansform 로써 사용된다.
def percent_price_change(yesterday, today):
return today["closing_price"] / yesterday["closing_price"] - 1
def day_over_day_changes(grouped_rows):
# sort the rows by date
ordered = sorted(grouped_rows, key=picker("date"))
# zip with an offset to get pairs of consecutive days
return [{"symbol": today["symbol"],
"date": today["date"],
"change": percent_price_change(yesterday, today)}
for yesterday, today in zip(ordered, ordered[1:])]
@ 데이터를 "심볼" 별로 그룹핑하고, 이전날과 비교한 오늘의 종가의 증감비율을 계산하 day_over_say_changes 를 value_tansform 로 넘겨준다. change 키에 그 값들을 넣어준다.
changes_by_symbol = group_by(picker("symbol"), data, day_over_day_changes)
@ 모든 그룹들의 "Change" 의 값들중 max,min 구해서 하나의 거대한 리스트에 담는다.
all_changes = [change
for changes in changes_by_symbol.values()
for change in changes]
print "max change", max(all_changes, key=picker("change"))
print "min change", min(all_changes, key=picker("change"))
이 경우 평균을 0 으로 만들고, 표준편차를 최대 1로 만들면, 비교하기 편해질 것이다.
data = [[1, 20, 2],
[1, 30, 3],
[1, 40, 4]]def shape(A):
num_rows = len(A)
num_cols = len(A[0]) if A else 0
return num_rows, num_colsdef scale(data_matrix):
num_rows, num_cols = shape(data_matrix)
means = [mean(get_column(data_matrix,j))
for j in range(num_cols)]
stdevs = [standard_deviation(get_column(data_matrix,j))
for j in range(num_cols)]
return means, stdevs
def rescale(data_matrix):
means, stdevs = scale(data_matrix)
def rescaled(i, j):
if stdevs[j] > 0:
return (data_matrix[i][j] - means[j]) / stdevs[j]
else:
return data_matrix[i][j]
num_rows, num_cols = shape(data_matrix)
return make_matrix(num_rows, num_cols, rescaled)
X = [
[20.9666776351559, -13.1138080189357],
[22.7719907680008, -19.8890894944696],
[25.6687103160153, -11.9956004517219],
[18.0019794950564, -18.1989191165133],
....
[15.6563953929008, -17.2196961218915],
[25.2049825789225, -14.1592086208169]
]
def shape(A):
num_rows = len(A)
num_cols = len(A[0]) if A else 0
return num_rows, num_colsdef magnitude(v):
return math.sqrt(sum_of_squares(v))
def de_mean_matrix(A):
"""A 행렬의 모든 값에 해당 컬럼의 평균을 뺀 행렬을 리턴합니다"
nr, nc = shape(A)
column_means, _ = scale(A)
return make_matrix(nr, nc, lambda i, j: A[i][j] - column_means[j])def negate(f):
"""-f(x) 로 리턴한다. """
return lambda *args, **kwargs: -f(*args, **kwargs)
def negate_all(f):
"""모든 리턴을 -y 로 한다."""
return lambda *args, **kwargs: [-y for y in f(*args, **kwargs)# 8.4. 적절한 스텝 크기 정하기
def safe(f):
"""f 를 감싸고 it 를 리턴하는 새 함수를 정의한다."""def safe_f(*args, **kwargs):
try:
return f(*args, **kwargs)
except:
return float('inf') # this means "infinity" in Python
return safe_f
def maximize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):def minimize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):
""" 경사하강법을 이용하여 타겟 함수를 최소화할 세타를 찾는다."""
step_sizes = [100, 10, 1, 0.1, 0.01, 0.001, 0.0001, 0.00001]
theta = theta_0 # 세타 초기값
target_fn = safe(target_fn) # target_fn 의 safe 버전
value = target_fn(theta) # 최소화할 값
while True:
gradient = gradient_fn(theta)
next_thetas = [step(theta, gradient, -step_size)
for step_size in step_sizes]
# choose the one that minimizes the error function
next_theta = min(next_thetas, key=target_fn)
next_value = target_fn(next_theta)
# stop if we're "converging"
if abs(value - next_value) < tolerance:
return theta
else:
theta, value = next_theta, next_value
return minimize_batch(negate(target_fn),
negate_all(gradient_fn),
theta_0,
tolerance)def principal_component_analysis(X, num_components):# partial 은 functools 에서 제공하는 함수로 # https://www.pydanny.com/python-partials-are-fun.html 참고
def first_principal_component(X):
guess = [1 for _ in X[0]]
unscaled_maximizer = maximize_batch(
partial(directional_variance, X), # is now a function of w
partial(directional_variance_gradient, X), # is now a function of w
guess)
return direction(unscaled_maximizer)
components = []
for _ in range(num_components):
component = first_principal_component(X)
components.append(component)
X = remove_projection(X, component)
return components
Y = de_mean_matrix(X)
components = principal_component_analysis(Y, 2)
print "principal components", components
print "first point", Y[0]
print "first point transformed", transform_vector(Y[0], components)
PCA 결과
[[0.9238554090431896, 0.382741666377781], [-0.3827224539579983, 0.9238633682728025]]
[0.6663708720254604, 1.6869418499129427]
[1.2612932692676448, 1.3034686841532082]
전체 소스는 아래에 있다.
https://github.com/insightbook/Data-Science-from-Scratch/blob/master/code/ch10_working_with_data.py
레퍼런스:
밑바닥부터 배우는 데이터과학
'통계 & 머신러닝 & 딥러닝 ' 카테고리의 다른 글
파이썬 코딩으로 말하는 데이터 분석 - 7. 회귀분석 (최소제곱법,경사하강법) (1) | 2017.01.31 |
---|---|
파이썬 코딩으로 말하는 데이터 분석 - 6. 경사하강법 (0) | 2017.01.31 |
파이썬 코딩으로 말하는 데이터 분석 - 4. 연관 (Apriori 알고리즘) (0) | 2017.01.19 |
파이썬 코딩으로 말하는 데이터 분석 - 3. 군집화 (0) | 2017.01.15 |
파이썬 코딩으로 말하는 데이터 분석 - 2. 베이즈 확률 (0) | 2017.01.15 |