My Blog

Latest blog


Summary

 모델은 예측 성능이 높아야 유용하므로 근본적인 목적은 고품질의 모델을 만드는 것입니다. 따라서 알고리즘이 만들 모델의 평가 방법에 대해 알아보겠습니다.

    * 교차검증 모델 만들기 (11.1)
        - 모델을 훈련하고 어떤 성능 지표(정확도, 제곱 오차 등)를 사용하여 얼마나 잘 동작하는지 계산
        - training set에 한정해서 잘 동작하는 모델이 아니라 새로운 데이터에 대해서 잘 동작하길 기대
        - KFCV(k-fold cross-validation)을 사용하여 최종 성능을 산출

    기본 회귀 모델 만들기 (11.2)
        - 회귀 모델 평가는 결정계수($ R^{2} $값)을 사용
        - $ R^2 = 1 - \\frac{\\sum_{i} (y_{i}-\\hat{y}_{i})^2}{\\sum_{i} (y_{i}-\\bar{y}_{i})^2} $

    * 기본 분류 모델 만들기 (11.3)
        - 분류 모델의 성능을 측정하는 일반적인 방법은 랜덤한 추측보다 얼마나 더 나은지 비교하는 것

    이진 분류기의 예측 평가하기 (11.4)
        - 훈련된 분류 모델의 품질평가: sklearn의 cross_val_score 함수 사용하여 교차검증 수행할 때 scoring 매개변수에 성능 지표 중 하나 선택
            1) Accuracy(정확도): 

    * 희소한 데이터의 특성 줄이기 (9.5)
        - 희소 특성 행렬의 차원을 축소함: TSVD truncated singular value decomposition를 사용함
        - TSVD는 PCA와 비슷하지만 PCA와 달리 희소 특성 행렬에 사용할 수 있다는 장점을 가짐
        - 자연어 처리에서는 TSVD를 잠재 의미 분석(LSA latent semantic analysis)이라고도 부름


Code





Summary

 특성 선택(feature selection)은 고품질의 정보가 많은 특성은 선택하고 덜 유용한 특성은 버리는 방식입니다. 방식에는 필터, 래퍼, 임베디드 세 가지가 있습니다.
 필터 filter: 통계적 속성을 조사하여 가장 뛰어난 특성 선택
 래퍼 wrapper: 시행착오 통해 가장 높은 품질의 에측을 만드는 특성의 부분 조합 찾음
 임베디드 embedded: 학습 알고리즘의 훈련 단계를 확장하거나 일부로 구성하여 가장 좋은 특성의 부분 조합을 선택함

    * 분산을 기준으로 수치 특성 선택하기 (10.1)
        - 수치형 특성 중 분산이 낮은 특성(즉 정보가 거의 없는 특성)을 삭제함: sklearn.feature_selection.VarianceThreshold 사용

    분산을 기준으로 이진 특성 선택하기 (10.2)
        - 이진 범주형 특성 중 분산이 낮은 특성(즉 정보가 거의 없는 특성)을 삭제함. 베르누이 확률 변수의 분산이 기준값 이상인 특성을 선택함: sklearn.feature_selection.VarianceThreshold 사용

    * 상관관계가 큰 특성 다루기 (10.3)
        - 두 가지 특성의 상관관계가 크다면 담고 있는 정보가 매우 비슷하므로 중복된 특성을 포함하는 것과 같음. 따라서 이 중 하나를 삭제: 상관관계 행렬(correlation matrix)을 사용하여 상관관계가 큰 특성을 확인하고 삭제

    분류 작업에 관련 없는 특성 삭제하기 (10.4)
        - 범주형 타겟 벡터에서 관련 없는 특성 삭제하기: 카이제곱(chi-square) 통계를 사용
        - 카이제곱 통계는 두 범주형 벡터의 독립성을 평가
        - 특성이 수치형인 경우 각 특성과 타겟 벡터 사이에서 분산 분석(ANOVA)의 F-값을 사용


Code





Summary

 차원 축소를 위한 특성 추출(feature extraction)의 목적은 특성에 내재된 정보는 많이 유지하면서 특성 집합 $ \rho_{original} $을 새로운 집합 $ \rho_{new} $로 변환하는 것입니다. 특성 추출의 한 가지 단점은 만들어진 새로운 특성을 사람이 이해하지 못한다는 것입니다.
 해석 가능한 모델을 유지하고 싶다면 특성 선택(feature selection)을 통한 차원 축소가 더 나은 방법입니다.

    * 주성분을 사용해 특성 줄이기 (9.1)
        - 일련의 특성이 주어졌을 때 데이터의 분산을 유지하며 특성의 수 줄이기: sklearn의 PCA 사용. PCA는 비지도 학습 기법으로 타겟 벡터 정보를 사용하지 않고 특성 행렬만 이용함.
         pca = sklearn.decomposition.PCA(n_components=0.99, whiten=True)
        - 데이터가 선형적으로 구분되면 (즉, 다른 클래스 사이에 직선이나 초평면 hyperplane을 그릴 수 있다면) PCA가 잘 동작함

    선형적으로 구분되지 않은 데이터의 차원 축소하기 (9.2)
        - 커널 트릭을 사용하는 주성분 분석의 확장을 사용하여 비선형 차원 축소를 수행
         kpca = sklearn.decomposition.KernelPCA(kernel='rbf', gamma=15, n_components=1)
        - 커널이란 데이터를 투영하는 다른 방법. 커널 함수는 선형적으로 구분되지 않는 데이터를 선형적으로 구분되는 고차원으로 투영시킴

    * 클래스 분리를 최대화하여 특성 줄이기 (9.3)
        - 분류 모델에 사용될 특성을 줄임: 선형 판별 분석 (LDA linear discriminant analysis)을 사용하여 클래스를 최대한 분리하는 성분 축으로 특성을 투영함
         lda = sklearn.discriminant_analysis.LinearDiscriminantAnalysis(n_components=1)
        - LDA는 분류 알고리즘이지만 차원 축소에도 자주 사용됨. PCA와 유사하지만 PCA가 데이터에서 분산이 최대인 성분 축에만 관심이 있는 반면, LDA는 클래스 간의 차이를 최대화하는 추가적인 목적을 가짐. 또한 LDA는 타겟 벡터를 사용함

    행렬 분해를 사용하여 특성 줄이기 (9.4)
        - 음수가 아닌 특성 행렬이 있을 때 차원 축소하는 방법: 비음수 행렬 분해(NMF non-negative matrix factorization) 사용
         nmf = sklearn.decomposition.NMF(n_components=10, random_state=1)
        - NMF는 선형 차원 축소를 위한 비지도 학습 기법으로, 원하는 특성 개수 r이 주어지면 NMF는 다음과 같이 특성 행렬을 분해함
         $ \mathbf{V} \approx \mathbf{W} \mathbf{H} $
         W는 nxr 크기 행렬   
         H는 rxd 크기 행렬 
         r값을 조절하여 필요한 차원 축소의 양을 정할 수 있음

    * 희소한 데이터의 특성 줄이기 (9.5)
        - 희소 특성 행렬의 차원을 축소함: TSVD truncated singular value decomposition를 사용함
        - TSVD는 PCA와 비슷하지만 PCA와 달리 희소 특성 행렬에 사용할 수 있다는 장점을 가짐
        - 자연어 처리에서는 TSVD를 잠재 의미 분석(LSA latent semantic analysis)이라고도 부름


Code





Summary

 범주형 데이터를 머신러닝에 알맞은 특성으로 변환하는 다양한 전략을 소개합니다.

    * 범주형 데이터 인코딩
        - 순서가 없는 범주형 특성 인코딩: sklearn의 LabelBinarizer 사용하여 one-hot encoding (5.1)
         one_hot = LabelBinarizer()
         one_hot.fit_transform(feature)
        - 순서가 있는 범주형 특성 인코딩: pandas dataframe의 replace 메서드 사용. 문자열 레이블을 수치값으로 변환 (5.2)
         scale_mapper = {'Low': 1, 'Medium': 2, 'High': 3}
         dataframe['Score'].replace(scale_mapper)
        - 특성 딕셔너리를 인코딩: sklearn의 DictVectorizer 사용. 기본적으로 sparse matrix 반환 (5.3)
         dictvectorizer.fit_transform(dictionary)

    누락된 클래스 값 대체하기 (5.4)
        - 머신러닝 분류 알고리즘을 훈련하여 누락된 값을 예측. KNN 분류기 사용
        - 누락된 값을 특성에서 가장 자주 등장하는 값으로 채우기. sklearn의 SimpleImputer 사용

    불균형 클래스 다루기 (5.5)
        - 더 많은 데이터 모으기
        - 불가능하면 모델 평가 지표 바꾸기: accuracy보다 precision, recall, F1-measure, ROC curve 등
        - 잘 동작하지 않으면 클래스 가중치 매개변수 사용하기
        - 혹은 다운샘플링 or 업샘플링 코려하기


Code





Summary

 정량적 데이터를 머신러닝에 알맞은 특성으로 변환하는 다양한 전략을 소개합니다.

    * 특성 스케일 바꾸기 (4.1)
        - 특성 배열의 scale 조정: sklearn의 MinMaxScaler 메서드 사용. 일반적으로 0 ~ 1이나 -1 ~ +1 사이로 조정.
         minmax_scale = sklearn.preprocessing.MinMaxScaler(feature_range=(0, 1))
         minmax_scale.fit_transform(feature)
        - fit 메서드: 특성의 min, max 계산
        - transform 메서드: 특성의 scale 조정
        - training set와 test set의 scale을 따로 조정하면 안됨. 조정하고자 구한 min, max를 똑같이 사용해야함.
        - Neural network에는 min-max scaling을 권장함

    특성 표준화하기 (4.2)
        - 특성을 mean 0, std 1이 되도록 변환: sklearn의 StandardScaler 메서드 사용.
         scaler = sklearn.preprocessing.StandardScaler()
         standardized = scaler.fit_transform(feature)
        - 변환된 특성은 원본 값이 특성 평균에서 몇 표준편차만큼 떨어져 있는지 표현 (z-score)
        - PCA 분석은 표준화가 잘 맞음
        - 데이터에 이상치가 많다면 특성의 mean과 std에 영향을 미치므로 표준화에 부정적인 영향을 미침
        - 이런 경우 median과 IQR을 사용하여 scale 변환: sklearn의 RobustScaler 메서드 사용. 데이터에서 median 빼고 IQR로 나눔
         robust_scaler = sklearn.preprocessing.RobustScaler()
         robust_standardized = robust_scaler.fit_transform(feature)

    정규화하기 (4.3)
        - 샘플 특성값을 전체 길이가 1인 단위 norm이 되도록 변환: norm 매개변수와 함께 Normalizer 클래스 사용.
         normalizer = sklearn.preprocessing.Normalizer(norm='l2')
         normalizer.transform(feature)
        - 이런 종류의 scaling은 각 단어나 n개의 단어 그룹이 특성인 텍스트 분류와 같이, 유사한 특성이 많을 때 종종 사용
        - Normalizer는 세 가지 노름 옵션 제공
            1. L2 (유클리드 노름): default. 두 지점 사이를 잇는 직선 거리
            2. L1 (맨하튼 노름): 택시 노름. 두 지점 사이를 사람이 도보를 따라 걷는 것과 같음
            3. max: 각 행의 max로 행의 값을 나눔

    다항 특성과 교차항 특성 생성하기 (4.4)
        - 다항 특성 (polynominal): feature와 target 사이에 비선형 관계가 있다는 가정을 추가할 때 사용. feature x에 변동 효과를 주입함. 예) 주요 질병에 걸릴 확률에 나이가 미치는 영향
        - 교차항 (interaction): 한 feature의 효과가 다른 feature에 의존하는 경우 사용. 예) 설탕을 넣었는지 여부, 커피를 저었는지 여부 → 커피의 달달함
        - sklearn의 PolynomialFeatures 클래스 사용

    특성 변환하기 (4.5)
        - FunctionTransformer: 하나 이상의 특성에 사용자 정의 변환을 적용함.
         new_transformer = FunctionTransformer(new_function)
         new_transformer.transform(features)
        - pandas의 apply도 동일한 변환을 수행함
         df.apply(new_function)

    이상치
        - 이상치 감지하기: 1사분위보다 1.5IQR 이상 작은 값. 3사분위보다 1.5IQR 이상 큰 값. (4.6)
        - 이상치 다루기
            1. 이상치 삭제
             houses[houses['kitchen'] < 3]
            2. 이상치로 표시하고 특성의 하나로 포함시키기
             houses['outlier'] = np.where(houses['kitchen'] < 3, 0, 1)
            3. 이상치의 영향이 줄어들도록 특성을 변환하기
             houses['log_of_square_feet'] = [ np.log(x) for x in houses['square_feet'] ]

    특성 이산화하기 (4.8)
        - Binarizer: 임곗값에 따라 특성을 둘로 나누기
         binarizer = Binarizer(18)
         binarizer.fit_transform(age)
        - digitize: 수치 특성을 여러 임곗값에 따라 나누니
         np.digitize(age, bins=[20, 30, 64])


Code





Summary

 Data wrangling은 원본 데이터를 정제하고 사용 가능한 형태로 구성하기 위한 변환 과정을 광범위하게 의미하는 비공식적인 용어입니다. 사용하는 가장 일반적인 구조는 데이터프레임입니다.

    * 데이터프레임 만들기 (3.1)
        - pandas에 데이터프레임 객체 만들 수 있는 다양한 방법 존재
        - DataFrame 클래스 사용: pd.DataFrame()
        - 원본 리스트 전달: pd.DataFrame(data, columns=['a', 'b'])
        - numpy 배열 주입: pd.DataFrame(np.array(data), columns=['a', 'b'])
        - dictionary 전달: pd.DataFrame(dictionary)

    데이터 설명하기 (3.2)
        - 차원 확인: dataframe.shape
        - 열 개수 확인: dataframe.count() (3.7)
        - 수치형 열 통계값 확인: dataframe.describe()
        - 수치형 열 상관계수 확인: dataframe.corr() (3.7)
        - 수치형 열 공분산 확인: dataframe.cov() (3.7)

    데이터프레임 탐색하기 (3.3)
        - loc: 데이터프레임 인덱스가 label(문자열 등)일 때 사용.
         dataframe.loc['hubert']
        - iloc: 데이터프레임의 위치 참조.
         dataframe.iloc[0]
        - loc, iloc 메서드의 슬라이싱은 python 슬라이싱과 달리 마지막 인덱스를 포함

    데이터프레임 수정
        - 값 치환: replace 메서드. (3.5)
         dataframe['column'].replace('hubert', 'ashley') 
        - 열 이름 변경: rename 메서드. (3.6)
         dataframe.rename(columns={'Name': 'Nickname'}) 
        - 열 삭제 I: drop 메서드와 열 이름. (3.10)
         dataframe.drop('Name', axis=1) 
        - 열 삭제 II: drop 메서드와 열 인덱스. (3.10)
         dataframe.drop(dataframe.columns[0], axis=1) 
        - 행 삭제 I: 불리언 조건. (3.11)
         dataframe[dataframe['Name'] != False] 
        - 행 삭제 II: 행 인덱스. (3.11)
         dataframe[dataframe.index != 0] 
        - 중복행 삭제: drop_duplicates 메서드 사용 (3.12)

    데이터프레임 고유한 값 처리 (3.8)
        - 열 내부 고유한 값 찾기: unique 메서드.
         dataframe['Name'].unique()
        - 열 내부 고유한 값 count: value_counts 메서드. 
         dataframe['Name'].value_counts()
        - 데이터프레임 전체 고유한 값 count: nunique 메서드.
         dataframe.nunique()

    데이터프레임 누락된 값 (3.9)
        - 누락 값 여부 확인: isnull/notnull 메서드.
         dataframe['Name'].isnull()

    데이터프레임 그룹핑
        - 값에 따라 행 그룹핑: groupby 메서드.
         datafeamr.groupby(['Name'])['Age'].mean() (3.13)
        - 시간에 따라 행 그룹핑: resample 메서드. index를 time range(datetime format)로 변경한 뒤 적용.
         dataframe.resample('W').sum() (3.14)
        - 그룹에 함수 적용하기: groupby로 행을 그룹핑하고 각 그룹에 apply 메서드 연결.
          dataframe.groupby('Name').apply(lambda x: x.count()) (3.17)

    데이터프레임 모든 열 원소에 함수 적용하기 (3.16)
        - apply 메서드: 열의 모든 원소에 내장 함수나 사용자 정의 함수 적용. 매개변수를 지정할 수 있음.
         dataframe['Name'].apply(uppercase)
         dataframe['Name'].apply(labbda x, age: x < age, age=40)
        - map 메서드: apply와 비슷하지만 dictionary를 input으로 넣을 수 있음.
         dataframe['Name'].map({True: 1, False: 0})

    데이터프레임 연결하기 (3.18)
        - 행 방향으로 연결하기: concat 함수에 axis=0 매개변수 사용.
         pd.concat([dataframe_a, dataframe_b], axis=0)
        - 열 방향으로 연결하기: concat 함수에 axis=1 매개변수 사용.
         pd.concat([dataframe_a, dataframe_b], axis=1)

    데이터프레임 병합하기 (3.19)
        - inner join: merge 메서드 사용하며 on 매개변수에 병합 열 지정.
         pd.merge(dataframe_a, dataframe_b, on='Name')
        - outer/left/right join: merge 메서드 사용하며 how 매개변수에 outer/left/right 사용.
         pd.merge((dataframe_a, dataframe_b, on='Name', how='outer')
        - left_on & right_on: 각 데이터프레임에서 병합하기 위한 열 이름 지정.
         pd.merge(dataframe_a, dataframe_b, left_on='Name', right_on='Age')
        - left_index & right_index: 열 기준 대신 인덱스를 기준으로 병합.
         pd.merge(datafeamr_a, dataframe_b, left_index=True, right_index=True)

    * Summary in Summary
        - merge 연산을 위해 세 가지 사항을 지정
            1. 병합할 두 개의 데이터프레임 지정
            2. 병합하기 위한 열 이름 지정
            3. 'how' 매개변수로 병합연산 종류 지정
                1) inner: 두 데이터프레임에 모두 존재하는 행만 반환
                2) outer: 두 데이터프레임의 모든 행 반환
                3) left: 왼쪽 데이터프레임의 모든 행 반환
                4) right: 오른쪽 데이터프레임의 모든 행 반환


Code





Summary

 머신러닝 작업의 첫 번째 단계는 데이터를 불러오는 것입니다.
 CSV 파일, SQL 데이터베이스 같은 다양한 소스에서 데이터를 적재하는 방법을 알아봅니다. pandas 라이브러리의 다양한 도구를 사용합니다. 모의 데이터 생성은 scikit-learn을 사용합니다.

    토이 데이터셋 (2.1)
        - load_boston: 보스턴 주택 가격에 대한 503개 샘플 데이터셋입니다. 회귀 알고리즘
        - load_iris: 붓꽃 샘플 치수에 대한 150개 샘플 데이터셋입니다. 분류 알고리즘
        - load_digits: 손으로 쓴 숫자 이미지 1,979개 샘플 데이터셋입니다. 이미지 분류 작업

    모의 데이터셋 (2.2)
        - 선형회귀: scikit-learn의 make_regression 함수 사용. 실수 특성 행렬과 실수 타겟 벡터를 반환
        - 분류: scikit-learn의 make_classification 함수 사용. 실수 특성 행렬과 클래스의 소속을 나타내는 정수 타겟 벡터 반환
        - 군집: scikit-learn의 make_blobs 함수 사용. 특성 행렬과 클래스의 소속을 나타내는 정수 타겟 벡터 반환 

    파일 적재
        - csv: pandas 라이브러리의 read_csv 함수 사용 (2.3)
        - excel: pandas 라이브러리의 read_excel 함수 사용 (2.4)
        - json: pandas 라이브러리의 read_json 함수 사용 (2.5)
        - SQL database: pandas 라이브러리의 read_sql_query 함수 사용 (2.6)


Code





Summary

 머신러닝 데이터를 다루기 위한 기본 도구인 벡터, 행렬, 배열을 알아봅니다.

    벡터
        - 1차원 배열로 만듭니다. (1.1)

    행렬
        - numpy의 empty 함수는 초기값 대신 크기만 지정하여 임의의 값이 채워진 배열을 만듭니다. (1.2)
        - numpy의 zeros 함수는 0으로 채운 배열을 만듭니다. (1.2)
        - numpy의 ones 함수는 1로 채운 배열을 만듭니다. (1.2)
        - numpy의 full 함수는 특정 값으로 채운 배열을 만듭니다. (1.2)
        - 행렬의 크기, 원소 개수, 차원을 알고 싶을 때 → shape, size, ndim 속성 사용 (1.5) 

    배열
        - vectorize로 벡터화 연산 적용하기 (1.6)
        - numpy의 broadcasting (1.6)
        - 배열 크기만 변경하고 싶을 때 → numpy의 reshape 함수 사용 (1.9)

    벡터나 행렬 전치하기 
        - T 메서드나 transpose 메서드를 사용 (1.10)

    행렬의 랭크 구하기 (1.12) 
        - 행렬의 랭크는 행이나 열이 만든 벡터 공간의 차원으로 선형 독립적인 행 또는 열 개수입니다.
        - numpy 선형대수 메서드인 matrix_rank를 사용
        - linalg 모듈의 svd 함수로 특잇값을 구한 다음 0이 아닌 값 수를 헤아리는 방법으로 구할 수 있음 

    행렬식, 대각원소, 대각합, 고윳값과 고유벡터, 역행렬 
        - 행렬식: numpy 선형대수 메서드인 det를 사용 (1.13)
        - 대각원소: numpy 선형대수 메서드인 diagonal 사용 (1.14)
        - 대각합: numpy 선형대수 메서드인 trace 사용 (1.15)
        - 고윳값과 고유벡터: numpy 선형대수 모듈의 eig 함수 사용 (1.16)
        - 역행렬: numpy 선형대수 모듈의 inv 함수 사용 (1.20)


Code