코딩하는 해맑은 거북이
인공지능(AI) 기초 다지기 (9) 본문
본 게시물의 내용은 '인공지능(AI) 기초 다지기(부스트코스)' 강의를 듣고 작성하였다.
해당 글은 4-2. Pandas II / 확률론 맛보기 2가지 파트를 다룬다.
1. Pandas II
2. 확률론 맛보기
1. Pandas II
Groupby I
▶ Groupby
- df.groupby(묶음의 기준이 되는 컬럼)[적용받는 컬럼].적용받는연산()
- SQL groupby 명령어와 같음
- split → apply → combine
- 과정을 거쳐 연산함
# 예제 데이터
ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)
df
df.groupby("Team")["Points"].sum()
df.groupby("Team")["Points"].mean()
▶ Hierarchical index
- Groupby 명령의 결과물도 결국은 dataframe
- 두 개의 column으로 groupby를 할 경우, index가 두 개 생성된다.
- 한 개 이상의 column을 묶을 수 있음. 이때 2개의 index가 구성된 것을 Hierarchical index라고 부른다.
h_index = df.groupby(["Team", "Year"])["Points"].sum()
h_index
h_index.index
h_index["Devils":"Kings"]
- unstack()
Group으로 묶어진 데이터를 matrix 형태로 전환해줌
h_index.unstack()
h_index.unstack().stack() # stack() 함수로 되돌릴수도 있음
- reset_index()
index를 없애주면서 풀어서 보여주는 함수
h_index.reset_index() # index를 없애주면서 풀어서 보여준다.
- swaplevel()
index level을 변경할 수 있음, 아래의 예제에서 "Year"과 "Team"의 위치가 바뀐 것을 볼 수 있다.
h_index.swaplevel()
sort_index(level=0) 함수를 통해 "Year" index를 기준으로 sort 할 수 있다.
h_index.swaplevel().sort_index(level=0)
- sort_values()
연산된 값을 기준으로 정렬해서 보여준다.
h_index.sort_values()
Q. h_index의 타입은? Series
index가 2개 있다고해서 DF가 아니라 Series이다.
type(h_index)
- operations
index level을 기준으로 기본 연산 수행 가능하다.
h_index.sum(level=0)
h_index.sum(level=1)
Groupby II
▶ grouped
Groupby에 의해 split된 상태를 추출 가능하다.
→ Tuple 형태로 그룹의 key, value 값이 추출된다.
grouped = df.groupby("Team")
for name,group in grouped:
print (name)
print (group)
Q. group의 타입은? DataFrame
type(group)
특정 key값을 가진 그룹의 정보만 추출 가능 : get_group()
grouped.get_group("Devils")
* 추출된 group 정보에는 세 가지 유형의 apply가 가능함
- Aggregation: 요약된 통계정보를 추출해 줌
- Transformation: 해당 정보를 변환해줌
- Filtration: 특정 정보를 제거 하여 보여주는 필터링 기능
▶ Aggregation
column 별로 연산을 해주되, group별로 데이터를 출력해준다.
grouped.agg(sum)
grouped.agg(max)
import numpy as np
grouped.agg(np.mean)
특정 column에 여러개의 function을 apply 할 수 도 있음
grouped['Points'].agg([np.sum, np.mean, np.std])
▶ transformation
Aggregation과 달리 key 값 별로 요약된 정보가 아니다!
개별 데이터의 변환을 지원한다.
transform : grouped된 상태에서 모든 값을 다 지정해주는 함수이다.
단, max나 min 처럼 Series 데이터에 적용되는 데이터들은 key값을 기준으로 Grouped된 데이터 기준
df
score = lambda x: (x.max())
grouped.transform(score)
score = lambda x: (x - x.mean()) / x.std()
grouped.transform(score)
▶ filter
특정 조건으로 데이터를 검색할 때 사용한다.
df["Team"].value_counts()
df.groupby('Team').filter(lambda x: len(x) >= 3) # 위의 결과로 봤을때 3이상 인 건 Riders, Kings
df.groupby('Team').filter(lambda x: x["Points"].max() > 800)
Case Study
- 원래 통화량 데이터
df_phone = pd.read_csv("phone_data.csv")
df_phone.head()
df_phone.dtypes
- 시간과 데이터 종류가 정리된 통화량 데이터
# 문자 형태의 date를 datetime 타입으로 변경해주기
import dateutil
df_phone['date'] = df_phone['date'].apply(dateutil.parser.parse, dayfirst=True)
df_phone.head()
df_phone.dtypes
df_phone.groupby('month')['duration'].sum()
df_phone.groupby('month')['duration'].sum().plot() # 월별 통화량 그래프
df_phone[df_phone['item'] == 'call'].groupby('month')['duration'].sum()
df_phone[df_phone['item'] == 'call'].groupby('month')['duration'].sum().plot()
df_phone.groupby(['month', 'item'])['duration'].count()
df_phone.groupby(['month', 'item'])['duration'].count().unstack().plot()
df_phone.groupby('month', as_index=False).agg({"duration": "sum"})
# as_index=False : 'month'를 index로 설정하지 않는다는 것.
df_phone.groupby('month').agg({"duration": "sum"})
df_phone.groupby('month').agg({"duration": "sum"}).reset_index()
df_phone.groupby(['month', 'item']).agg({'duration':sum, # find the sum of the durations for each group
'network_type': "count", # find the number of network type entries
'date': 'first'}) # get the first date per group
df_phone.groupby(['month', 'item']).agg({'duration': [min], # find the min, max, and sum of the duration column
'network_type': "count", # find the number of network type entries
'date': [min, 'first', 'nunique']}) # get the min, first, and number of unique dates
grouped = df_phone.groupby('month').agg( {"duration" : [min, max, np.mean]})
grouped
grouped.columns = grouped.columns.droplevel(level=0)
grouped
# column 이름 변경
grouped.rename(columns={"min": "min_duration", "max": "max_duration", "mean": "mean_duration"})
grouped = df_phone.groupby('month').agg( {"duration" : [min, max, np.mean]})
grouped
grouped.columns = grouped.columns.droplevel(level=0)
grouped
# 앞에 duration을 붙여줘서 어떤 column과 연산을 했는지 알아보기 쉽게 해줌
grouped.add_prefix("duration_")
Pivot table & Crosstab
▶ Pivot Table
- 우리가 excel에서 보던 것
- Index축은 groupby와 동일함
- Column에 추가로 labeling값을 추가하여, Value에 numerictype값을 aggregation하는 형태
df_phone = pd.read_csv("phone_data.csv")
df_phone['date'] = df_phone['date'].apply(dateutil.parser.parse, dayfirst=True)
df_phone.head()
df_phone.pivot_table(values=["duration"],
index=[df_phone.month,df_phone.item],
columns=df_phone.network,
aggfunc="sum",
fill_value=0)
# 물론 groupby를 써도 비슷한 결과를 가져올 수 있음
df_phone.groupby(["month", "item", "network"])["duration"].sum().unstack()
▶ Crosstab
- 특허 두 칼럼에 교차 빈도,비율,덧셈 등을 구할 때 사용
- Pivottable의 특수한 형태
- User-ItemRatingMatrix등을 만들 때 사용가능함
import numpy as np
df_movie = pd.read_csv("/content/drive/My Drive/movie_rating.csv")
df_movie.head()
df_movie.pivot_table(["rating"],
index=df_movie.critic,
columns=df_movie.title,
aggfunc="sum",
fill_value=0)
pd.crosstab(index=df_movie.critic,columns=df_movie.title,values=df_movie.rating,
aggfunc="first").fillna(0)
df_movie.groupby(["critic","title"]).agg({"rating":"first"}).unstack().fillna(0)
Merge & Concat
▶ Merge
- SQL에서 많이 사용하는 Merge와 같은 기능
- 두 개의 데이터를 하나로 합침
raw_data = {
'subject_id': ['1', '2', '3', '4', '5', '7', '8', '9', '10', '11'],
'test_score': [51, 15, 15, 61, 16, 14, 15, 1, 61, 16]}
df_a = pd.DataFrame(raw_data, columns = ['subject_id', 'test_score'])
df_a
raw_data = {
'subject_id': ['4', '5', '6', '7', '8'],
'first_name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
'last_name': ['Bonder', 'Black', 'Balwner', 'Brice', 'Btisan']}
df_b = pd.DataFrame(raw_data, columns = ['subject_id', 'first_name', 'last_name'])
df_b
- 두 dataframe의 column이 같을 때 : pd.merge(df_a, df_b, on='subject_id')
pd.merge(df_a, df_b, on='subject_id')
- 두 dataframe의 column이 다를 때 : pd.merge(df_a, df_b, left_on='subject_id', right_on='subject_id')
pd.merge(df_a, df_b, left_on='subject_id', right_on='subject_id')
- join method
- left join
pd.merge(df_a, df_b, on='subject_id', how='left')
- right join
pd.merge(df_a, df_b, on='subject_id', how='right')
- full(outer) join
pd.merge(df_a, df_b, on='subject_id', how='outer')
- inner join
default 가 inner join 이다.
pd.merge(df_a, df_b, on='subject_id', how='inner')
- inner based join
pd.merge(df_a, df_b, right_index=True, left_index=True)
▶ Concat
- 같은 형태의 데이터를 붙이는 연산작업
raw_data = {
'subject_id': ['1', '2', '3', '4', '5'],
'first_name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
'last_name': ['Anderson', 'Ackerman', 'Ali', 'Aoni', 'Atiches']}
df_a = pd.DataFrame(raw_data, columns = ['subject_id', 'first_name', 'last_name'])
df_a
raw_data = {
'subject_id': ['4', '5', '6', '7', '8'],
'first_name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
'last_name': ['Bonder', 'Black', 'Balwner', 'Brice', 'Btisan']}
df_b = pd.DataFrame(raw_data, columns = ['subject_id', 'first_name', 'last_name'])
df_b
df_new = pd.concat([df_a, df_b])
df_new.reset_index(drop=True)
df_a.append(df_b)
df_new = pd.concat([df_a, df_b], axis=1)
df_new.reset_index(drop=True)
persistence
▶ Database connection
- Dataloading시 db connection기능을 제공한다.
# Database 연결 코드
import sqlite3 #pymysql <- 설치
conn = sqlite3.connect("./data/flights.db")
cur = conn.cursor()
cur.execute("select * from airlines limit 5;")
results = cur.fetchall()
results
# db 연결 conn을 사용하여 dataframe 생성
df_airplines = pd.read_sql_query("select * from airlines;", conn)
df_airplines
▶ XLS persistence
- Dataframe의 엑셀 추출 코드
- Xls 엔진으로 openpyxls 또는 XlsxWrite 사용
writer = pd.ExcelWriter('./data/df_routes.xlsx', engine='xlsxwriter')
df_routes.to_excel(writer, sheet_name='Sheet1')
▶ Pickle persistence
- 가장 일반적인 python파일 persistence
- to_pickle,read_pickle 함수 사용
df_routes.to_pickle("./data/df_routes.pickle")
df_routes_pickle = pd.read_pickle("./data/df_routes.pickle")
2. 확률론 맛보기
- 딥러닝에서 확률론이 왜 필요한가요?
- 딥러닝은 확률론 기반의 기계학습 이론에 바탕을 두고 있다.
- 기계학습에서 사용되는 손실함수(loss function)들의 작동 원리는 데이터 공간을 통계적으로 해석해서 유도하게 된다.
- 회귀 분석에서 손실함수로 사용되는 L2-Norm은 예측오차의 분산을 가장 최소화하는 방향으로 학습을 유도한다.
- 분류 문제에서 사용되는 교차엔트로피(cross-entropy)는 모델 예측의 불확실성을 최소화하는 방향으로 학습하도록 유도한다.
- 분산 및 불확실성을 최소화하기 위해서는 측정하는 방법을 알아야 한다.
- → 두 대상을 측정하는 방법을 통계학에서 제공하기 때문에 기계학습을 이해하려면 확률론의 기본 개념을 알아야 한다.
- 확률분포는 데이터의 초상화
- 데이터공간을 X x Y라 표기하고 D는 데이터공간에서 데이터를 추출하는 분포이다.
- 데이터는 확률변수로 (x, y) ~ D 라 표기한다.
파란색 점 : 데이터 공간상에서 관측한 데이터
데이터를 추출할 때 확률 변수를 사용하게 되고, 확률변수로 추출한 데이터의 분포를 D라고 한다.
- 결합분포(Joint distribution) P(x, y)는 D를 모델링한다.
위의 그림에서 파란색 점들은 연속확률분포처럼 보이는 확률분포를 띄고있지만, 빨간색 칸막이로 나누게 되면 이산확률분포처럼 생각할 수 있다. 그럼 각각의 칸에 대해서 파란색 점의 갯수를 세면, 현재 주어진 데이터의 분포를 가지고 원래 확률 분포의 D를 모델링 할 수 있다.
- P(x)는 입력 x에 대한 주변확률분포(Marginal distribution)로 y에 대한 정보를 주진 않는다.
주변확률분포 P(x)는 결합분포 P(x, y)에서 유도 가능하다.
- 조건부확률분포 P(x|y)는 데이터 공간에서 입력 x와 출력 y 사이의 관계를 모델링한다.
2개의 경우가 가능하다 - P(x|y) or P(y|x)
P(x|y)는 특정 클래스가 주어진 조건에서 데이터의 확률분포를 보여준다.
* y가 주어져 있는 상황에서 x에 대한 확률분포
cf) 이산확률변수 vs 연속확률변수
확률변수는 확률분포 D에 따라 이산형(discrete)과 연속형(continuous) 확률변수로 구분하게 된다.
→ 데이터공간 X x Y에 의해 결정 (X)
→ 확률분포 D에 의해 결정된다. (O)
이산형 확률변수는 확률변수가 가질 수 있는 경우의 수를 모두 고려하여 확률을 더해서 모델링한다.
연속형 확률변수는 데이터 공간에서 정의된 확률변수의 밀도(density) 위에서의 적분을 통해 모델링한다.
* 모든 확률변수가 위의 2가지로만 구분되는 것은 아니다.
- 조건부확률과 기계학습
- 조건부확률 P(y|x)는 입력변수 x에 대해 정답이 y일 확률을 의미한다.
→ 연속확률분포의 경우 P(y|x)는 확률이 아닌 밀도로 해석한다는 것에 주의!
- 로지스틱 회귀에서 사용했던 선형모델과 소프트맥스 함수의 결합은 데이터에서 추출된 패턴을 기반으로 확률을 해석하는데 사용된다.
- 분류 문제에서 softmax(WΦ+b)은 데이터 x로부터 추출된 특징패턴 Φ(x)과 가중치행렬 W을 통해 조건부확률 P(y|x)을 계산한다.
→ P(y|Φ(x)) 라고 써도 된다.
- 회귀 문제의 경우 조건부기대값 E[y|x]을 추정한다.
→ 조건부기대값은 E||y - f(x)||2 을 최소화하는 함수 f(x)와 일치하기 때문에 종종 사용한다.
→ 통계적 모형에서 원하고자 하는 목적에 따라 통계추정이 달라질 수 있다. (중앙값 등)
- 딥러닝은 다층신경망을 사용하여 데이터로부터 특징패턴 Φ을 추출한다
→ 특징패턴을 학습하기 위해 어떤 손실함수를 사용할지는 기계학습 문제와 모델에 의해 결정된다.
Q. 기대값이 뭔가요?
- 확률분포가 주어지면 데이터를 분석하는 데 사용 가능한 여러 종류의 통계적 범함수(statistical functional)를 계산할 수 있다.
- 기대값(expectation)은 데이터를 대표하는 통계량이면서 동시에 확률분포를 통해 다른 통계적 범함수를 계산하는데 사용된다.
- 평균(mean)이랑 동일한 개념으로 사용할 수 있다. 그러나, 기계학습에서 사용하는 경우에는 훨씬 폭넒게 사용된다.
- 기대값을 이용해 분산, 첨도, 공분산 등 여러 통계량을 계산할 수 있다.
- 몬테카를로 샘플링
- 기계학습의 많은 문제들은 확률분포를 명시적으로 모를 때가 대부분이다.
- 확률분포를 모를 때 데이터를 이용하여 기대값을 계산하려면 몬테카를로 (Monte Carlo) 샘플링 방법을 사용해야 한다.
→ 몬테카를로는 이산형이든 연속형이든 상관없이 성립한다.
→ 중요한 것은 샘플링 하는 분포에서 독립적으로 항상 샘플링을 해줘야 몬테카를로 (Monte Carlo) 샘플링이 작동한다.
- 몬테카를로 샘플링은 독립추출만 보장된다면 대수의 법칙(law of large number)에 의해 수렴성을 보장한다.
→ 이 방법을 통해 목표로 하는 기대값을 근사시킬 수 있다.
* 몬테카를로 예제 : 적분 계산하기
Q. 함수 \(f(x) = e^{-x^2}\)의 [-1, 1] 상에서 적분값을 어떻게 구할까?
f(x)의 적분을 해석적으로 구하는건 불가능하다.
균등분포이므로 구간 [-1, 1]의 길이는 2이므로 적분값을 2로 나누면 기대값을 계산하는 것과 같으므로 몬테카를로 방법을 사용할 수 있다.
* 문제점 : 샘플사이즈가 적게되면 몬테카를로 방법으로 구해도 오차범위가 굉장히 커질 수 있고 참값에서 멀어질 수 있다.
그래서 적절한 샘플의 갯수를 조절해줘야 원하고자하는 적분값을 구할 수 있다.
'AI' 카테고리의 다른 글
딥러닝 기초 다지기 (5) - 끝 (0) | 2023.03.21 |
---|---|
인공지능(AI) 기초 다지기 (10) (0) | 2023.03.09 |
[딥러닝] RNN (Recurrent Neural Network) (0) | 2022.12.31 |
[딥러닝] CNN (Convolutional Neural Network) (0) | 2022.12.31 |
딥러닝 기초 다지기 (4) (0) | 2022.12.26 |