반응형

[목차]

 

1. 현재 상태

2. 내 커리어 여정

3. 취업준비생으로서 겪었던 어려움

4. 내가 추천하는 방법

5. 앞으로의 커리어

 

1. 현재 상태


나는 현재 국내 회계법인 컨설팅 회사의 데이터 관련 조직에서 일하고 있다.

 

이 조직에서 하는 일은 크게는 Data Science와 Data Platform / Governance / Road Map 수립 등이 있다.

 

Data Science는 고객의 문제를 정의 후 알고리즘, 통계 등을 이용하여 해결하는 업무이다.

Data Platform은 빅데이터 플랫폼 수립, 데이터 인프라 등과 관련된 전반적인 컨설팅 업무를 의미한다.

그 외 Governance / Road Map 등은 데이터를 어떻게 관리하고, 프로젝트를 시작할 지 모르는 기업들을 컨설팅하는 서비스이다.

 

2. 내 커리어 여정


나는 BI(Business Intelligence) 부문에서 커리어를 시작했다.

쉽게 얘기하자면, 시각화 개발이고, QlikView를 내 처음 Tool로써 접했다.

 

개인적으로 시각화 툴로써 데이터를 접했던 과정이, 어떻게 데이터를 핸들링하고 가공해야 하는지 이해하고 그 과정을 직접 시각화로 확인할 수 있어서 좋은 시작점이었다고 본다.

 

그리고 회사를 현재의 컨설팅 회사로 옮겨 지표 설계 ~ 개발까지의 업무를 모두 진행해보고 있다.

추가된 것은, 내가 고객의 비즈니스를 최대한 이해하고, 회사의 Asset을 활용하여 고객에게 선제시 한다는 점이다.

 

3. 취준생으로서 겪었던 어려움


취업 준비를 할 당시만 해도 데이터 분야의 정보가 너무 적었다.

 

다들 개발 얘기를 하거나, 머신러닝이나  AI 이야기를 했을 뿐이고,

그리고 Python이 얼마나 중요하고 시각화를 만드는 기술이 어떻고라는 기술에 대해서 주로 이야기가 오갔다.

 

그래서 "진짜 데이터로 Business를 어떻게 해결한다는걸까?" 라는 질문에 대답을 해줄 수 있는 사람이 극히 드물었다. 드문 정도가 아니라 내게는 없었다.

 

그래서 면접 때마다 공허한 얘기를 늘어놓아야 했는데, 이게 내가 맞닥드린 가장 큰 어려움이었다.

 

더불어 나는 대학시절을 탱탱 놀다가 취업전선에 뛰어들어 Tool 들에 익숙하지 못했는데, 이게 무척 높은 허들이었다.

 

4. 내가 추천하는 지원 방법


그럼에도 불구하고 내가 적용했던 방법은 바닥부터 시작하는 일이었다.

 

BI 개발을 시작했던 회사의 면접 때가 생각나는데, 나는 연속 낙방을 하느라 조금 지쳐있었다.

일부 회사에서는 내가 아무것도 없으면서, 무언가를 만들어본양 허풍을 늘어놓기도 했다.

 

그러나 면접관들은 거짓을 잘 분별할 줄 안다.

내가 이 업에서 조금만 있어봐도 누가 허황된 말을 하는지 금방 판별할 수 있다.

 

그래서 나는 면접에서 나를 내려놓고, 나는 아무것도 아는 게 없지만 열정을 가지고 배워볼 자신이 있다고 스스로를 어필했다. 그리고 이 점을 당시 나를 뽑아주셨던 본부장님께서 좋게 보신 모양이다.

일은 들어와서 배워도 되지만, 얼마나 열심히 하려고 하는지, 진실하게 원하는 지를 평가하신 것 같았다.

 

결론을 얘기하자면, 어떤 회사라도 첫 커리어로 괜찮다.

너무 대기업에 들어가려고 하거나, 네카라쿠배당토에 목 맬 필요는 없지 싶다.

 

어느 회사든 들어가서 일을 하고, 공부하면서 기술과 데이터를 이해하기 시작하면 그 다음 길은 점점 넓어질 것이기 때문이다. 나는 그렇게 느끼고 있으며, 앞으로도 그렇게 될 것이라 생각한다.

 

5. 앞으로의 커리어


사실 나 역시도 너무나 많은 고민을 하고 있다. 특히 아래와 같은 고민을 하며 살고 있다.

 

개발자의 끝은 무엇인가? 컨설턴트의 끝은 무엇인가? 데이터 분석가는 20년 30년 분석가로서 남을 수 있는가? 앞으로 나는 살아남을 직업을 선택하고 있는가? 

 

과거 선배들의 말은 이미 지나간 과거에 유효하며, 세상은 너무 빨리 바뀌고 기술도 자꾸 변한다. 그래서 그들의 말을 참고는 하되 너무 맹신할 필요는 없다. 그들도 모르게 낡았을 수도 있기 때문이다.

 

따라서 Data를 무기로 가져가되, 여러 기술에 관심을 가지고 Business에 이런 기술들을 접목할 지 계속 고민하는 것 만이 앞으로의 변화에 대응하는 길이라고 본다.

반응형
반응형

경사하강법 정의


경사 하강법(傾斜下降法, Gradient descent)은 1차 근삿값 발견용 최적화 알고리즘이다. 기본 개념은 함수의 기울기(경사)를 구하고 경사의 반대 방향으로 계속 이동시켜 극값에 이를 때까지 반복시키는 것이다
위키피디아

이 개념을 숙지하기 위해서는 비용함수라는 개념을 먼저 알아두면 좋다.

비용함수

$$y = w_1*x_1 + w_0$$ 라는 회귀식이 있을 경우, 이 함수의 *_비용함수 RSS**는 다음과 같다. (약간의 회귀분석에 대한 개념이 필요)

$$RSS(w_0, w_1) = \frac{1}{N}\sum_{i=1}^{N}(y_i-(w_0+w_1*x_i))^2$$

여기서 N은 학습데이터의 총 건수이며, i는 각 데이터포인트이다. 회귀에서는 이 RSS는 비용이라고 하며 w변수로 구성되는 RSS를 비용함수, 또는 손실함수(loss function)라고 한다. 머신러닝 회귀 알고리즘에서는 데이터를 계속 학습하면서 이 비용함수가 반환되는 값을 지속해서 감소시키고, 최종적으로는 더이상 감소하지 않는 최소의 오류값을 구하고자 한다.
오류값을 지속해서 작아지게 하는 방향으로 W값을 계속 업데이트해 나가며, 오류값이 더 이상 작아지지 않으면 그 오류값을 최소 비용으로 판단하고 그 W를 최적의 파라미터로 판단한다.

머신러닝에서 쓰이는 이유

그럼 비용함수가 최소가 되는 W파라미터를 어떻게 구할 수 있을까? 하는 대답에 경사하강법이 사용되는 것이다. 모든 변수(x)를 미분하여 최소값을 가지는 계수를 찾아내는 방법이 있을 수 있으나 아래의 이유로 경사하강법이 쓰인다.

  • 실제 분석에서는 함수의 형태가 복잡하므로 미분계수와 그 근을 계산하기 어려움
  • 컴퓨터로는 미분계산과정의 구현보다 경사하강법 구현이 더 쉬움
  • 데이터 양이 많을 수록 경사하강법이 계산량 측면에서 효율적임

경사하강법의 수식, 유도 및 원리

경사하강법을 유도하는 원리는 아래 사이트가 잘 정리되어 있어 참고했다.
https://angeloyeo.github.io/2020/08/16/gradient_descent.html

파이썬 코드 구현

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

np.random.seed(0)

# y = 4X + 6을 근사, 임의의 값은 노이즈를 위해 부여
X = 2 * np.random.rand(100,1) # 0~1 사이의 random 소수 
y = 6 + 4*X+ np.random.randn(100,1)
plt.scatter(X,y)

png

def get_cost(y, y_pred):
    N = len(y)
    cost = np.sum(np.square(y - y_pred))/N
    return cost
# w1과 w0를 업데이트할 w1_update, w0_update를 반환
def get_weight_updates(w1, w0, X, y, learning_rate=0.01):
    N = len(y)

    w1_update = np.zeros_like(w1)
    w0_update = np.zeros_like(w0)

    y_pred = np.dot(X, w1.T) + w0
    diff = y - y_pred

    w0_factors = np.ones((N,1))

    # w1과 w0를 업데이트할 w1_update와 w0_update 계산
    w1_update = -(2/N)*learning_rate*(np.dot(X.T, diff))
    w0_update = -(2/N)*learning_rate*(np.dot(w0_factors.T, diff))

    return w1_update, w0_update
def gradient_descent_stpes(X, y, iters=10000):
    # 초기값 0으로 설정
    w0 = np.zeros((1,1))
    w1 = np.zeros((1,1))

    # 인자로 주어진 iters 만큼 반복적으로 get_weight_updates() 호출해 w1, w0 업데이트
    for ind in range(iters):
        w1_update, w0_update = get_weight_updates(w1, w0, X, y, learning_rate=0.01)
        w1 = w1 - w1_update
        w0 = w0 - w0_update

    return w1, w0
def get_cost(y, y_pred):
    N = len(y)
    cost = np.sum(np.square(y - y_pred))/N
    return cost

w1, w0 = gradient_descent_stpes(X,y, iters=1000)
print(f"w1 : {w1[0,0]:.3f}, w0 : {w0[0,0]:.3f}")
y_pred = w1[0, 0]*X + w0
print("GD Total Cost", round(get_cost(y, y_pred),4))
w1 : 4.022, w0 : 6.162
GD Total Cost 0.9935
plt.scatter(X,y)
plt.plot(X, y_pred)

png

확률적 경사하강법


확률적 경사 하강법(Stochastic Gradient Descent)는 경사 하강법과 다르게 한번 학습할 때 모든 데이터에 대해 가중치를 조절하는 것이 아니라, 램덤하게 추출한 일부 데이터에 대해 가중치를 조절함. 결과적으로 속도는 개선되었지만 최적 해의 정확도는 낮다.

img1

출처: 흰고래의꿈

파이썬 코드 구현

def stochastic_gradient_descent_stpes(X, y, batch_size=10, iters=1000):
    w0 = np.zeros((1,1))
    w1 = np.zeros((1,1))
    prev_cost = 100000
    iter_index = 0

    for ind in range(iters):
        np.random.seed(ind)
        # 전체 X,y 데이터에서 랜덤하게 batch_size만큼 데이터 추출하여 sample_X, sample_y로 저장
        stochastic_random_index = np.random.permutation(X.shape[0])
        sample_X = X[stochastic_random_index[0:batch_size]]
        sample_y = y[stochastic_random_index[0:batch_size]]
        # 랜덤하게 batch_size만큼 추출된 데이터 기반으로 w1_update, w0_update 계산 후 업데이트
        w1_update, w0_update = get_weight_updates(w1, w0, sample_X, sample_y, learning_rate = 0.01)
        w1 = w1 - w1_update
        w0 = w0 - w0_update

    return w1, w0
w1, w0 = stochastic_gradient_descent_stpes(X, y, iters= 1000)
print("w1 :", round(w1[0,0], 3), "w0:", round(w0[0,0], 3))
y_pred = w1[0, 0]*X + w0
print("Stochastic Gradient Descent Total cost : ",get_cost(y, y_pred))
w1 : 4.028 w0: 6.156
Stochastic Gradient Descent Total cost :  0.9937111256675345

참고 사이트

반응형
반응형

고유값과 고유벡터

고유값과 고유벡터는 앞서 활용한 공분산행렬, 그리고 앞에 설명할 주성분 분석과 뗄 수 없는 관계이다. 따라서 PCA의 메커니즘을 제대로 이해하기 위해서는 고유값과 고유벡터가 의마하는 바를 제대로 이해하는 게 좋다.

고유값과 고유벡터 설명


$$X=\begin{bmatrix} 1 \\ 1 \end{bmatrix}$$ 이라는 행렬이 있다고 가정해보자. 이 행렬에 만약 $$A=\begin{bmatrix} 2&1 \\ 1&2 \end{bmatrix}$$를 선형변환하면 이렇게 계산할 수 있다.

  • $$AX= \begin{bmatrix} 2&1 \\ 1&2 \end{bmatrix}\begin{bmatrix} 1 \\ 1 \end{bmatrix}=\begin{bmatrix} 3 \\ 3 \end{bmatrix}$$
    즉 어떤 벡터에 A를 곱하니 벡터의 방향은 그대로이고 길이만 변하였다고 표현할 수 있다. 다시 말하면 아래 좌표평면에 있는 (1,1) 벡터가 (3,3)가지 방향의 변환 없이 그대로 이동한 것이다.

img

여기서 $$AX = \lambda X$$ 가 되는 $$\lambda$$ 값이 바로 고유값(eigen value)이다. 조금 더 정리를 해보자

  • $$AX - \lambda IX = (A - \lambda I)X = 0$$
  • $$det(A - \lambda I) = 0$$ (det는 determinant이며, $$ad-bc$$의 형태로 행렬값을 계산하는 수식임)
  • $$det(A - \lambda I) = det\begin{bmatrix} 2-\lambda&1 \\ 1&2-\lambda \end{bmatrix} = 0$$
  • $$(2-\lambda)^2 -1 = (\lambda-1)(\lambda-3) = 0 $$
  • $$\lambda =2$$ or $$\lambda =3$$
  • 즉 고유값은 2 또는 3이다

그럼 여기서 고유벡터를 구하면 아래와 같이 볼 수 있다

  • 고유값이 3인 경우, $$\begin{bmatrix} 2&1 \\ 1&2 \end{bmatrix}\begin{bmatrix} X_1 \\ X_2 \end{bmatrix} = 3\begin{bmatrix} X_1 \ X_2 \end{bmatrix}$$
    • $$2X_1 + X_2 = 3X_1$$
    • $$X_1 + 2X_2 = 3X_2$$
    • $$X_1 = X_2$$
    • 가장 쉬운 형태의 고유행렬로 $$\begin{bmatrix} X_1 \\ X_2 \end{bmatrix} = \begin{bmatrix} 1 \\ 1 \end{bmatrix} $$로 볼 수 있다.
  • 고유값이 1인 경우도 동일하게 구할 수 있다

고유값과 고유벡터의 의미


$$A$$ 행렬을 공분산 행렬(covariance matrix)이라고 생각해보자.

  • $$\begin{bmatrix} 2&1 \\ 1&2 \end{bmatrix}$$ 행렬의 고유값은 1과 3이다
  • 고유값의 합은 4로, 두 분산의 합(2+2)과 같다
  • 고유값의 곱은 $$det(A) = (2_2 - 1_1)$$과 동일
  • 분산정보는 최대한 해치지 않으면서 차원을 축소하기 위해 고유값과 고유벡터를 찾아낸 것
  • 고유벡터는 행렬 A를 곱하더라도 방향이 변하지 않고 그 크기만 변하는 벡터를 의미함

주성분 분석(PCA)

주성분 분석의 목적


주성분 분석의 목적 및 핵심은 아래와 같다.

  • 고차원의 데이터를 저차원으로 줄이는 것
  • 공통된 변수들을 줄여서 주성분을 찾는 것
    • 사용된 변수의 개수 > 주성분의 개수
  • 하지만 전체 데이터의 분산에 영향을 주어서는 안됨

주성분 뽑아낼 때 원칙


  • 분산이 가장 커지는 축을 첫 번째 주성분으로 두고, 그 다음 분산이 두번째로 커지는 축을 두 번째 주성분으로 두는 식으로 주성분은 추출

  • 각 주성분은 서로간 90도 직교함

    • 공분산 행렬의 고유벡터 개념임
  • 위에서 고유값 3일 때 계산되는 첫 번째 고유벡터가 바로 첫 번째 주성분(PC1)이 된다. 즉, $$ \begin{bmatrix} 1 \ 1 \end{bmatrix} $$ 고유벡터가 첫 번째 주성분 축이 된다는 의미임

  • 원본 데이터가 있을 경우 먼저 표준화가 진행된다

  • 표준화가 되었다고 가정하고, $$ \begin{bmatrix} 70&80 \\ 50&40 \\ 70&90 \end{bmatrix} \begin{bmatrix} 1 \\ 1 \end{bmatrix} $$ 이 계산 되어 최종 $$\begin{bmatrix} 150 \\ 90 \\ 160 \end{bmatrix} $$이 되어 새로운 축으로 반영되는 것이다. 이 축은 국어와 영어점수를 설명하는 '언어능력점수' 정도로 해석해 볼 수 있다.

  • 2차원 좌표평면에서 설명해야 이해가 빠른데, 해당 설명은 참고유튜브를 참조하자

  • 고유값이 1일 때 나왔던 주성분 PC2(고유벡터)는 분산의 설명도에 따라 사용할 수도, 안 할 수도 있다

  • PC1과 PC2의 상관관계는 0이다(고유값의 계산관계 상 0이 될 수 밖에 없다.)

주성분 분석을 사용할 때


  • 주성분 분석은 언제나 가능한가?
    • 주성분 분석은 데이터의 이면에 보이지 않는 원인이 있음을 전제
    • 즉 국어점수와 영어점수를 설명하는 '언어능력'이 있음을 생각하는 것
  • 주성분 분석에 적합한 데이터란 무엇인가?
    • 구형성 검증(Bartlett's test of sphericity)
    • "상관관계가 0이라면 주성분이 존재할 수 있는가?"를 생각하는 것
    • 즉 상관관계가 업는 형태라면 주성분 분석을 할 수 없음

PCA 실습


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns # seaborn
import warnings
warnings.filterwarnings("ignore") # 경고메세지 무시

df = pd.read_excel("./data/pca_credit_card/card.xls", header=1).iloc[:,1:]
print(df.shape)
df.head(3)
(30000, 24)
LIMIT_BAL SEX EDUCATION MARRIAGE AGE PAY_0 PAY_2 PAY_3 PAY_4 PAY_5 ... BILL_AMT4 BILL_AMT5 BILL_AMT6 PAY_AMT1 PAY_AMT2 PAY_AMT3 PAY_AMT4 PAY_AMT5 PAY_AMT6 default payment next month
0 20000 2 2 1 24 2 2 -1 -1 -2 ... 0 0 0 0 689 0 0 0 0 1
1 120000 2 2 2 26 -1 2 0 0 0 ... 3272 3455 3261 0 1000 1000 1000 0 2000 1
2 90000 2 2 2 34 0 0 0 0 0 ... 14331 14948 15549 1518 1500 1000 1000 1000 5000 0

3 rows × 24 columns

default payment next month가 Target 이며 1이면 "다음달 연체", 0이면 "정상납"임

df.rename(columns={"PAY_0":"PAY_1", "default payment next month":"default"}, inplace=True)
y_target = df["default"]
X_features = df.drop("default", axis=1)
corr = X_features.corr()
plt.figure(figsize=(14,14))
sns.heatmap(corr, annot=True, fmt='.1g')

img

  • PAY_1 ~ 6까지의 상관도와 BILL_AMT1 ~ 6까지의 상관도가 각각 높음
  • PCA로 변환을 시행
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler

# BILL
cols_bill = ["BILL_AMT" + str(i) for i in range(1,7)]
print("대상 속성명 :", cols_bill)

# PCA 객체 생성 후 변환
scaler = StandardScaler()
df_cols_scaled = scaler.fit_transform(X_features[cols_bill])
pca = PCA(n_components=2)
pca.fit(df_cols_scaled)
print("PCA Component 별 변동성 :", pca.explained_variance_ratio_)
대상 속성명 : ['BILL_AMT1', 'BILL_AMT2', 'BILL_AMT3', 'BILL_AMT4', 'BILL_AMT5', 'BILL_AMT6']
PCA Component 별 변동성 : [0.90555253 0.0509867 ]
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

rcf = RandomForestClassifier(n_estimators=300, random_state=156)
scores = cross_val_score(rcf, X_features, y_target, scoring="accuracy", cv=3)

print("개별 정확도 :", scores)
print("평균정확도:", np.round(np.mean(scores),3))
개별 정확도 : [0.8083 0.8196 0.8232]
평균정확도: 0.817
# 원본 데이터 세트에 먼저 StandardScaler
scaler = StandardScaler()
df_scaled = scaler.fit_transform(X_features)

# 6개의 컴포넌트를 가진 PCA 변환 수행 cross_val_score()로 분류 예측 수행
pca = PCA(n_components=6)
df_pca = pca.fit_transform(df_scaled)
scores_pca = cross_val_score(rcf, df_pca, y_target, scoring="accuracy", cv=3)

print("개별 정확도 :", scores_pca)
print("평균정확도:", np.round(np.mean(scores_pca),3))
개별 정확도 : [0.7905 0.7976 0.8021]
평균정확도: 0.797
# 6개의 변수만으로도 성능의 차이가 크게 없음
pca.explained_variance_ratio_
array([0.28448215, 0.17818817, 0.06743307, 0.06401153, 0.04457547,
       0.04161736])
  • 결론적으로 PCA를 사용할 때는 변수가 많고, X변수 간의 상관관계가 있다 싶을 때 사용한다
  • 그리고 원본 데이터를 돌려보고 시간이 많이 걸린다 싶을 때 차원 축소를 고려해볼 수 있다
  • 대신 각 변수의 해석의 문제가 남는다.
반응형
반응형

차원축소(Dimension Reduction)


변수의 개수를 줄이는 것을 의미함

차원축소를 하는 이유


  • 변수가 많으면 다 사용하는 것이 비효율적인 경우
  • 간혹 변수의 개수보다 관찰값의 개수가 적은 경우
  • 변수 간 상관관계가 있는 경우
    • 국어, 영어, 사회 -> 인문영역
    • 수학, 물리 -> 수리탐구영역
    • 위와 같이 5개의 변수를 두 가지의 변수로 축소하여 표현 가능

차원축소를 하는 방법


  • 상관관계가 높은 변수들을 묶어보기
  • 공분산행렬을 이용
  • Covariance Matrix는 Corrlation Matrix와 유사
  • 두 변수의 공변(covariate)량과 관계가 있음

치원축소를 할 때 주의사항


  • 원 데이터의 분산을 최대한 유지하는 것이 중요(분산이 커지거나 작아지는 것은 지양)
  • 원 데이터와 다른 새로운 데이터가 생성되는 것
  • 분석자의 의도대로 축소되지 않거나 해석이 어려운 경우도 발생함

공분산과 상관관계

공분산


공분산 공식은 아래와 같다.

$$\frac{1}{n-1}\sum_{i=1}^{N}(x_i-\bar{x})(y_i-\bar{y})$$

  • 두 변수의 방향을 의미함
  • 두 변수의 공분산행렬은 다음과 같이 표현된다. 여기서 a는 첫 번째 변수의 분산, b는 공분산, c는 두 번째 변수의 분산으로 표현된다. 만약 국어와 영어점수가 있다고 한다면 a는 국어의 분산, c는 영어의 분산, 그리고 b는 공분산이 된다.

$$\begin{pmatrix}a & b \\ b & c \end{pmatrix}$$

  • 분산은 언제나 양수이나 공분산은 음수일 수도 있음
  • 공분산이 양수라면 X와 Y는 같은 방향으로 움직인다는 의미
  • 반대로 공분산이 음수라면 X,Y는 음의 상관관계를 갖는다는 의미
  • 공분산이 0이라면? -> 상관관계가 없다는 뜻
  • 다만 상관관계가 얼마나 큰지는 제대로 설명하지 못함
    참고유튜브

상관관계


상관계수(p)는 아래와 같이 계산이 된다.
$$p = $$ $$Cov(x,y) \over \sqrt{Var(x)*Var(y)}$$

  • 공분산을 각각의 분산으로 나누어 표준화한 개념
  • 상관계수는 -1에서 1 사이의 값을 가지며 각 -1과 1에 근접할수록 상관관계가 있는 것을 판단 가능
반응형
반응형

Matplotlib를 항상 까먹어서 다시 정리하였음!

Matplotlib

# 패키지
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

가장 간단한 예제

  • plt.show()의 역할은 print의 역할과 동일하다고 보면 된다.
  • 즉 결과를 Out으로 내는 게 아니라 Print한다는 의미이나, 실질적으로 큰 차이는 없다고 본다.
  • r-을 통해 빨간색 라인 타입을 보일 수 있음
fig, ax = plt.subplots()  # Create a figure containing a single axes.
ax.plot([1,2,3,4], [1,4,2,3] ,'r-') # 꺾은선
ax.scatter([1,2,3,4], [1,4,2,3]) # 산점도
plt.xlabel("X Label") # X 축
plt.ylabel("Y Label") # Y 축
ax.set_title("test") # 제목
plt.show()

img

Figure의 구성

  • figure는 ax를 담는 그릇이다. 각 ax는 하나의 차트, 또는 좌표평면이라고 보면 될 것 같다.
fig = plt.figure()  # 빈 Figure
fig, ax = plt.subplots()  # 하나의 ax를 가진 Figure
fig, axs = plt.subplots(2, 2)  # 2X2 Grid의 Figure
<Figure size 432x288 with 0 Axes>

png

Axes

  • Ax는 Figure안에 담기는 차트 객체를 의미한다.
  • 각 Ax는 set_title()함수를 통해 이름을 정할 수도 있고, set_xlabel(), set_ylabel()을 통해 축 이름을 정할 수 있다.

Subplots 연습

  • Subplot은 현실 시각화 분석에서 가장 많이 쓰이는 함수이다.
  • plt.tight_layout()은 subplot끼리 겹치는 경우 이를 해결해 줄 수 있다.
x = np.linspace(0, 10, 6)
y = x ** 2

plt.subplot(1,2,1)
plt.plot(x,y,'r')

plt.subplot(1,2,2)
plt.plot(y,x,'b')
[<matplotlib.lines.Line2D at 0x129ae2c3940>]

png

fig, axes = plt.subplots(nrows=1, ncols=2)
plt.tight_layout() # Layout을 화면에 맞춰주는 함수

for ax in axes:
    ax.plot(x,y)

png

  • axes를 쳐보면 array 객체임을 알 수 있음, 따라서 위 명령어 처럼 ax를 반복문으로 루프를 돌릴 수 있음
axes
array([<AxesSubplot:>, <AxesSubplot:>], dtype=object)

Plot function이 받는 데이터 형태

  • nmupy.array 형태를 기본적으로 받음
  • ax.scatter에서 c인자는 color를 의미하고 s인자는 size를 의미한다.
  • 그래서 c인자에넌 0~49까지의 사이의 값이 들어가고, size는 d도 마찬가지이다.
b = np.matrix([[1,2],[3,4]])
b_asarray = np.asarray(b)
np.random.seed(19680801)  # seed
data = {'a': np.arange(50),
        'c': np.random.randint(0, 50, 50),
        'd': np.random.randn(50)}
data['b'] = data['a'] + 10 * np.random.randn(50)
data['d'] = np.abs(data['d']) * 100

fig, ax = plt.subplots(figsize=(5, 2.7))
ax.scatter('a', 'b', c='c', s='d', data=data)
ax.set_xlabel('entry a')
ax.set_ylabel('entry b');

png

코딩 스타일

코딩 스타일은 크게 아래와 같이 두 가지로 나눈다.

1. OO 스타일 : fig와 ax를 정확히 정의하고 들어감

2. pyplot자동화 : pyplot이 알아서 figure와 ax를 컨트롤하도록 함

# OO 스타일
x = np.linspace(0, 2, 100)  # Sample data.

# Note that even in the OO-style, we use `.pyplot.figure` to create the Figure.
fig, ax = plt.subplots(figsize=(5, 2.7))
ax.plot(x, x, label='linear')  # Plot some data on the axes.
ax.plot(x, x**2, label='quadratic')  # Plot more data on the axes...
ax.plot(x, x**3, label='cubic')  # ... and some more.
ax.set_xlabel('x label')  # Add an x-label to the axes.
ax.set_ylabel('y label')  # Add a y-label to the axes.
ax.set_title("Simple Plot")  # Add a title to the axes.
ax.legend();  # Add a legend.

png

# pyplot  스타일
x = np.linspace(0, 2, 100)  # Sample data.

plt.figure(figsize=(5, 2.7))
plt.plot(x, x, label='linear')  # Plot some data on the (implicit) axes.
plt.plot(x, x**2, label='quadratic')  # etc.
plt.plot(x, x**3, label='cubic')
plt.xlabel('x label')
plt.ylabel('y label')
plt.title("Simple Plot")
plt.legend();

png

Plot Styling

  • plot에 color인자와 linewidth, linestyle등을 지정해서 스타일링 가능하다.
  • alpha를 통해 투명도도 조정 가능
data1, data2, data3, data4 = np.random.randn(4, 100)  

fig, ax = plt.subplots(figsize=(5, 2.7))
x = np.arange(len(data1))
ax.plot(x, np.cumsum(data1), color='blue', linewidth=3, linestyle='--')
l, = ax.plot(x, np.cumsum(data2), color='orange', linewidth=2)
l.set_linestyle(':');

png

colors

  • facecoloredgecolor등을 설정 가능합
fig, ax = plt.subplots(figsize=(5, 2.7))
ax.scatter(data1, data2, s=50, facecolor='C0', edgecolor='k');

png

fig = plt.figure()

ax = fig.add_axes([0,0,0.5,0.5])
ax.plot(x,y, color='r', marker='o', markersize=10, markerfacecolor="yellow", markeredgecolor="green") # 색 부여, 마커 부여
plt.show()

png

marker

fig, ax = plt.subplots(figsize=(5, 2.7))
ax.plot(data1, 'o', label='data1')
ax.plot(data2, 'd', label='data2')
ax.plot(data3, 'v', label='data3')
ax.plot(data4, 's', label='data4')
ax.legend();

png

Labeling Plots

  • fontsizecolor이용 가능하다.
mu, sigma = 115, 15
x = mu + sigma * np.random.randn(10000)
fig, ax = plt.subplots(figsize=(5, 2.7))
# the histogram of the data
n, bins, patches = ax.hist(x, 50, density=1, facecolor='C0', alpha=0.75)

# ax.set_xlabel('Length [cm]')
ax.set_xlabel('my data', fontsize=14, color='red')
ax.set_ylabel('Probability')
ax.set_title('Aardvark lengths\n (not really)')
ax.text(75, .025, r'$\mu=115,\ \sigma=15$')
ax.axis([55, 175, 0, 0.03])
ax.grid(True);

png

Limit

  • set_xlim, set_ylim을 통해 X축과 y축의 범위를 정의할 수 있다.
  • 작게 설정 시, Zoom-In 효과가 있다
fig = plt.figure()

ax = fig.add_axes([0,0,0.5,0.5])
ax.plot(x,y, color='r', marker='o', markersize=10, markerfacecolor="yellow", markeredgecolor="green") # 색 부여, 마커 부여
ax.set_xlim([0,10]) # x limit
ax.set_ylim([0,25]) # y limit
plt.show()

png

Legend(범례)

  • loc인자를 통해 위치를 정할 수 있으며 0일 때 자동 조정이며 0~10까지 숫자에 따라 위치를 조정 가능하다.
fig, ax = plt.subplots(figsize=(5, 2.7))
ax.plot(np.arange(len(data1)), data1, label='data1')
ax.plot(np.arange(len(data2)), data2, label='data2')
ax.plot(np.arange(len(data3)), data3, 'd', label='data3')
# ax.legend(loc=10); #10이면 한 가운데로 옴
ax.legend(loc=(0.76,0.63)) # 숫자로 부여 가능
<matplotlib.legend.Legend at 0x129b0480eb0>

png

참고사이트 : https://matplotlib.org/stable/tutorials/introductory/usage.html#types-of-inputs-to-plotting-functions

반응형

'Data > Python' 카테고리의 다른 글

Python seaborn 시각화 기본 정리  (0) 2022.04.02
반응형

Seaborn의 기본 내용 정리한 내용임

import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore") # 경고메세지 무시
# 펭귄데이터
penguins = sns.load_dataset("penguins")
penguins.info()
penguins.head()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 344 entries, 0 to 343
Data columns (total 7 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   species            344 non-null    object 
 1   island             344 non-null    object 
 2   bill_length_mm     342 non-null    float64
 3   bill_depth_mm      342 non-null    float64
 4   flipper_length_mm  342 non-null    float64
 5   body_mass_g        342 non-null    float64
 6   sex                333 non-null    object 
dtypes: float64(4), object(3)
memory usage: 18.9+ KB
  species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex
0 Adelie Torgersen 39.1 18.7 181.0 3750.0 Male
1 Adelie Torgersen 39.5 17.4 186.0 3800.0 Female
2 Adelie Torgersen 40.3 18.0 195.0 3250.0 Female
3 Adelie Torgersen NaN NaN NaN NaN NaN
4 Adelie Torgersen 36.7 19.3 193.0 3450.0 Female
#히스토그램
sns.histplot(data=penguins, x="flipper_length_mm", hue="species", multiple="stack")
<AxesSubplot:xlabel='flipper_length_mm', ylabel='Count'>

img

# kernel density estimation
sns.kdeplot(data=penguins, x="flipper_length_mm", hue="species", multiple="stack")
<AxesSubplot:xlabel='flipper_length_mm', ylabel='Density'>

img

Figure Level vs Axes Level Functions

  1. axes-level는 matplotlib.pyplot.axes를 기준으로 만들어지고
  2. Figure-level은 FacetGrid를 기준으로 만들어진다.

Distribution Plots

distplot

  • 분포 확인
  • kde차트와 히스토그램 확인가능
sns.distplot(penguins["flipper_length_mm"], bins=40)
# kde=False를 하면 kde차트는 사라짐
C:\Users\Jessie\anaconda3\lib\site-packages\seaborn\distributions.py:2619: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).
  warnings.warn(msg, FutureWarning)





<AxesSubplot:xlabel='flipper_length_mm', ylabel='Density'>

img

jointplot

  • Scatterplot을 기본으로 각 축의 분포 확인 가능
sns.jointplot(x="flipper_length_mm",y="bill_length_mm",data=penguins, hue="species")
# hue="species" - 색반환
# kind="hex" - 육각형 모양으로 반환
# kind="reg" - Regression plot
# kind="kde"  - 등고선
<seaborn.axisgrid.JointGrid at 0x165bc527550>

img

sns.jointplot(x="flipper_length_mm",y="bill_length_mm",data=penguins, kind="reg" )
<seaborn.axisgrid.JointGrid at 0x165bc4fe6d0>

img

pairplot

  • 모든 Numeric 변수에 대하여 Scatter plot과 분포도 그림
sns.pairplot(data=penguins, hue="species", palette="coolwarm")
<seaborn.axisgrid.PairGrid at 0x165bf0f27c0>

img

rugplot

sns.rugplot(penguins["flipper_length_mm"])
<AxesSubplot:xlabel='flipper_length_mm'>

img

Categoricla Plots

barplot

  • estimator인자는 Barplot의 y축을 계량하는 기준을 의미하며 default값은 mean이다.
import numpy as np
sns.barplot(data=penguins, x="species", y="flipper_length_mm", estimator=np.std) # 표준편차
<AxesSubplot:xlabel='species', ylabel='flipper_length_mm'>

img

countplot

sns.countplot(data=penguins, x="species")
<AxesSubplot:xlabel='species', ylabel='count'>

img

boxplot

sns.boxplot(x="species",y="bill_length_mm",data=penguins, hue="sex")
<AxesSubplot:xlabel='species', ylabel='bill_length_mm'>

img

viloin plot

sns.violinplot(x="species",y="bill_length_mm",data=penguins, hue="sex", split=True)
<AxesSubplot:xlabel='species', ylabel='bill_length_mm'>

img

stripplot

sns.stripplot(x="species",y="bill_length_mm",data=penguins, jitter=True, hue="sex", split=True)
C:\Users\Jessie\anaconda3\lib\site-packages\seaborn\categorical.py:2805: UserWarning: The `split` parameter has been renamed to `dodge`.
  warnings.warn(msg, UserWarning)





<AxesSubplot:xlabel='species', ylabel='bill_length_mm'>

img

swarmplot

  • stripplot과 violing plot의 조합으로 볼 수 있음
sns.swarmplot(x="species",y="bill_length_mm",data=penguins)
<AxesSubplot:xlabel='species', ylabel='bill_length_mm'>

img

Matrix chart

tc = penguins.corr()

Heatmap

  • annot=Ture 인자를 통해서 히트맵에 해당하는 셀의 값을 노출할 수 있다.
  • cmap을 통해 컬러맵 부여 가능
sns.heatmap(tc,annot=True, cmap="coolwarm")
<AxesSubplot:>

img

test = penguins.pivot_table(index="species", columns="island", values="bill_length_mm")
sns.heatmap(test, cmap="magma")
<AxesSubplot:xlabel='island', ylabel='species'>

img

Clustermap

sns.clustermap(tc, cmap="coolwarm", standard_scale=1, annot=True)
<seaborn.matrix.ClusterGrid at 0x165c2a16dc0>

img

Grid

iris = sns.load_dataset("iris")
iris.head()
  sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

PairGrid

g = sns.PairGrid(iris)
# g.map(plt.scatter) # scatter
g.map_diag(sns.distplot) # 사선에는 distplot
g.map_upper(plt.scatter) # 사선 상단에는 scatterplot
g.map_lower(sns.kdeplot) # 사선 아래에는 kdeplot
<seaborn.axisgrid.PairGrid at 0x165c7fc8790>

img

FacetGrid

  • Categorical한 변수를 기준으로 그래프를 쪼개서 볼 수 있음
  • Trellis(격자구조)의 개념이라고 생각하면 좋음
tips = sns.load_dataset("tips")
tips.head()
  total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
g = sns.FacetGrid(data=tips, col="time", row="smoker")
# g.map(sns.distplot, "total_bill")
g.map(plt.scatter, "total_bill", "tip")
<seaborn.axisgrid.FacetGrid at 0x165ca168850>

img

regplot

lmplot

sns.lmplot(x="total_bill", y="tip",data=tips, hue="sex", markers=['o','v'])
<seaborn.axisgrid.FacetGrid at 0x165ca196df0>

img

sns.lmplot(x="total_bill", y="tip",data=tips,col="sex",row="time") # auto FacetGrid
<seaborn.axisgrid.FacetGrid at 0x165ca32e400>

img

반응형

'Data > Python' 카테고리의 다른 글

Python Matploblib 시각화 기본  (0) 2022.04.02
반응형

Ridge 회귀 (L2 규제)


img

  • 선형 모델이며 최소적합법을 사용
  • 일반 회귀와 다른 점은 가중치(w 또는 β) 의 절대값을 최대한 작게 함
  • 즉 기울기를 0으로 만듬
  • 이렇게 하는 이유는 과대적합이 생기지 않도록 모델을 강제로 제한함을 의미

Lasso 회귀 (L1 규제)


img

  • Ridge에서와 마찬가지로 계수를 0에 가깝게 제한하는 것은 동일함
  • 하지만 정말로 0인 계수가 생기기도 함. 즉 제외되는 계수도 발생
  • 이는 자동으로 특성이 선택된다고 볼 수 있으며 가장 중요한 특성이 무엇인지 드러내 준다고 생각하면 됨
  • 간혹 Lasso를 이용하면 과속적합이 발생하기도 하는데, 이는 너무 많은 Feature를 Drop하여 모델을 못 쓰게 만드는 경우이다.

무엇을 사용할 것인가?


  • 일반적으로 Ridge 회귀를 분석에서 선호하는 편
  • 다만 분석하기 쉬운 모델을 고를 경우 Lasso가 더 좋은 선택이 될 수 있음
  • Lasso와 Ridge의 패널티를 결합한 ElasticNet이라는 것도 있음. 최상의 결과를 내기도 하지만 두 개의 매개변수를 조정해야 함.

참고 사이트

반응형
반응형

도움이 되는 사이트


출처 : 엘리의 드림코딩 - 정규표현식 깃허브(https://github.com/dream-ellie/regex)

Groups and ranges

 

Chracter

|

또는

()

그룹

[]

문자셋, 괄호안의 어떤 문자든

[^]

부정 문자셋, 괄호안의 어떤 문가 아닐때

(?:)

찾지만 기억하지는 않음

Quantifiers

Chracter

?

없거나 있거나 (zero or one)

*

없거나 있거나 많거나 (zero or more)

+

하나 또는 많이 (one or more)

{n}

n번 반복

{min,}

최소

{min,max}

최소, 그리고 최대

Boundary-type

Chracter

\b

단어 경계

\B

단어 경계가 아님

^

문장의 시작

$

문장의 끝

Character classes

 

Chracter

\

특수 문자가 아닌 문자

.

어떤 글자 (줄바꿈 문자 제외)

\d

digit 숫자

\D

digit 숫자 아님

\w

word 문자

\W

word 문자 아님

\s

space 공백

\S

space 공백 아님

 


Titanic Data 에서의 적용

 

Name 필드에는 아래와 같은 이름들이 있다.

 

Bonnell, Miss. Elizabeth

Nasser, Mrs. Nicholas (Adele Achem)

Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)

Williams-Lambert, Mr. Fletcher Fellows

Clarke, Mrs. Charles V (Ada Maria Winfield)

Ford, Miss. Doolina Margaret "Daisy"

Duff Gordon, Lady. (Lucille Christiana Sutherland) ("Mrs Morgan")

Rothes, the Countess. of (Lucy Noel Martha Dyer-Edwards)

 

 

 

여기에서 우리는 Miss, Mrs, Lady와 같은 호칭을 뽑아내려고 한다.

이 때 정규표현식을 사용해서 R에서 가져오게 되는데 아래와 같은 표현식을 사용한다.

 

full$Title <- gsub('(.*, )|(\\..*)', '', full$Name)

여기서 '\\'로 '\'가번 쓰이는 것은, R에서는 '\'를 '\\'로 써야 백대시로 인식하기 때문이다.

 

gsub은 대체시키는 함수이다.

대체시키려는 값과 대체시키는 값을 차례로 Paramter로 받는다.

 

결과는 아래와 같다.

 

(.*, ) - 콤마와 공백 앞에 있는 모든 값

| - 또는

(\..*) - 점 다음에 있는 모든 값

 

R에서 사용할 때는 \\를 \ 대신 사용한다는 것이 포인트였다.

정규표현식은 문자열을 다루기 위해서는 반드시 배워야할 필요가 있다는 점을 이해했다.

다음에 문자열을 다룰 때에는 좀더 편하게 다룰 수 있을 것 같다.

 

반응형

+ Recent posts