핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.

 

챕터 8. 차원 축소

많은 경우 머신러닝 문제는 훈련 샘플 각각이 수백만개의 특성을 가지고 있는데, 이는 훈련을 느리게 하며 성능을 좋지 않게 만든다. 이를 curse of dimensionality 라고 한다. 예를 들어 MNIST 이미지에서는 이미지 경계에 주로 흰색 픽셀이 있으므로 완전히 제거해도 많은 정보를 잃지 않는다. 또한 인접한 픽셀을 합치는 과정을 진행해도 많은 정보를 잃지 않는다. 차원을 축소시키면 일부 정보가 유실되어 훈련 속도가 빨라질 수는 있지만 성능이 조금 나빠질 수 있다. 하지만 어떤 경우에는 잡음이나 불필요한 세부사항을 걸러내 성능이 좋아지기도 한다.

 

8.1 차원의 저주

2차원에서 무작위 점을 선택한다면 경계선에서 0.001 이내에 위치할 가능성은 0.4%이지만, 10000차원이라면 이 가능성이 99.999999%보다 크다. 따라서 대다수의 점은 경계와 매우 가까이 있다. 또한 임의의 두 점 사이의 거리는 2차원에서 평균 0.52가 되지만 1000000차원에서는 평균 428.25가 된다. 즉, 고차원의 데이터셋은 매우 희박한 상태이며 차원의 저주를 해결하려면 데이터셋을 늘리면 되지만 기하급수적으로 필요량이 많아지므로 차원을 축소해야한다.

 

8.2 차원 축소를 위한 접근 방법

8.2.1 투영

많은 경우 특성들이 강하게 연결되어있어, 훈련 샘플이 저차원 subspace에 놓여있다. 이 경우 훈련 샘플들을 잘 투영하여 저차원으로 만드는 것이 좋다.

 

 

하지만 어떤 경우 데이터가 Swiss roll 처럼 생겨 공간이 뒤틀려있는데, 이런 경우에는 투영하면 더 구분하기 어려워진다.

 

 

8.2.2 매니폴드 학습

스위스 롤은 2D 매니폴드의 한 예시이다. 많은 차원 축소 알고리즘이 훈련 샘플이 놓여있는 manifold를 모델링 하는 식으로 작동하며 이를 manifold learning이라고 한다. 예를 들어 MNIST 데이터에서 무작위로 점을 찍은 이미지는 숫자로 보이지 않을 것이며 아주 일부만 숫자로 보일텐데, 숫자 이미지의 자유도는 랜덤 이미지의 자유도보다 훨씬 낮다는 뜻이다. 따라서 manifold assumption을 도입하여 저차원의 manifold로 압축한다. 하지만 경우에 따라 매니폴드를 펴기 전이 더 간단한 결정 경계를 가질 수도 있다. 

 

 

8.3 PCA

주성분 분석은 가장 인기 있는 차원 축소 알고리즘이다. hyperplane을 찾아 데이터를 투영시키는 방법이다.

 

8.3.1 분산 보존

데이터를 투영할 hyperplane을 찾을 때에, 투영된 데이터들 간의 거리가 멀 수록 좋다. 즉 분산을 최대화 하는 hyperplane을 찾아야 한다.

 

 

8.3.2 주성분

여러 개의 축을 찾을 때에, 우선 분산을 최대화 하는 첫 번째 축을 찾는다. 이후 첫 번째 축에 직교하고 남은 분산을 최대한 보존하는 두 번째 축을 찾는다. 이렇게 i개의 축을 찾는다. i번째 축을 정의하는 단위 벡터를 i번째 주성분 (PC) 라고 부른다.

 

분산을 최대화 하는 주성분을 찾을 때에는 행렬의 SVD 분해를 사용한다. X = U Sigma V^t 일 때, V의 행들이 주성분이다. numpy의 svd() 함수를 사용하면 된다.

 

8.3.3 d차원으로 투영하기

주성분을 모두 추출하였다면 이 중 최초 d개의 주성분(고윳값이 큰 순서)을 뽑아 데이터를 d차원으로 축소시킨다. 원래 데이터를 주성분들에 내적하면 데이터 변환이 완료된다.

 

8.3.4 사이킷런 사용하기

https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html

 

sklearn.decomposition.PCA — scikit-learn 0.22.1 documentation

 

scikit-learn.org

위 함수를 사용하여 간단하게 PCA 변환할 수 있다. components_ 변수를 사용하면 주성분을 확인할 수 있다.

 

8.3.5 설명된 분산의 비율

explaned_variance_ratio_ 변수에 저장된 주성분의 explaned variance ratio를 확인할 수 있다. 각각의 값은 해당 축이 데이터를 얼마나 설명해주는지 알려준다.

 

8.3.6 적절한 차원 수 선택하기

축소할 차원 수를 정하는 방법으로는, 설명된 분산의 합이 일정 수치(95% 등)이 될 때 까지 더하는 것이다. 데이터 시각화를 위한 축소에는 2개나 3개를 사용하는 것이 좋다. PCA의 n_components를 비율로 설정 할 수 있다.

 

8.3.7 압축을 위한 PCA

실제로 MNIST 데이터를 784개의 축에서 154개의 축으로 변환하면 눈으로 구분할 수 있다. 이를 역변환할 수 있지만, 100%의 데이터를 복구할 수는 없다. 재구성된 데이터와 실제 데이터 사이의 평균 제곱 거리를 reconstruction error라고 한다.

 

 

8.3.8 점진적 PCA

훈련 데이터 전체를 메모리에 올리지 않고 사용가능한 Incremental PCA 알고리즘이 있다. 

https://scikit-learn.org/stable/auto_examples/decomposition/plot_incremental_pca.html

 

Incremental PCA — scikit-learn 0.22.1 documentation

Note Click here to download the full example code or to run this example in your browser via Binder Incremental PCA Incremental principal component analysis (IPCA) is typically used as a replacement for principal component analysis (PCA) when the dataset t

scikit-learn.org

혹은 넘파이의 memmap 파이썬 클래스를 이용해 디스크의 데이터를 메모리에 올린 것 처럼 사용하여도 된다.

 

8.3.9 랜덤 PCA

PCA의 svd_solver를 "randomized" 로 지정하면 랜덤 PCA 알고리즘을 사용한다. 이는 확률적으로 첫 d개의 주성분에 대한 근삿값을 빠르게 찾는다. 계산 복잡도는 O(m n^2) + O(n^3) 에서 O(m d^2) + O(d^3) 이 된다.

 

8.4 커널 PCA

차원 축소 과정에서 선형 투영이 아닌 비선형에 대해 진행하는 것을 kernel PCA라고 한다. 

https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.KernelPCA.html

 

sklearn.decomposition.KernelPCA — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

8.4.1 커널 선택과 하이퍼파라미터 튜닝

kPCA 중 좋은 커널과 하이퍼파라미터를 선택하기 위하여, 여러 값들에 대해서 분류를 해보고, 이를 파이프라인으로 만들어 GridSearchCV를 해보는 것이 좋다. 가장 낮은 재구성 오차를 만드는 커널과 하이퍼파라미터를 선택하는 방법도 있지만 재구성이 쉽지 않다. 재구성을 하는 방법 중 하나는 투영된 샘플을 훈련 세트로, 원본 샘플을 타깃으로하는 지도 학습을 진행하는 것이다. fit_inverse_transform = True로 지정하면 자동으로 수행한다.

 

8.5 LLE

지역 선형 임베딩 (Locally Linear Embedding)은 또 다른 비선형 차원 축소 기술이다. 각 훈련 샘플이 가장 가까운 이웃에 얼마나 선형적으로 연관되어있는지 측정하여 이 관계가 가장 잘 보존되는 저차원 표현을 찾는 것이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.manifold.LocallyLinearEmbedding.html

 

sklearn.manifold.LocallyLinearEmbedding — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

LLE는 크게 두 과정으로 이루어져 있다. 각 알고리즘이 훈련 샘플에 대해 가까운 k개의 샘플을 찾아 선형함수로 원 샘플을 재구성한다. 이 선형함수를 적용하여 오차가 최소가 되는 저차원 벡터들을 찾는다.

 

8.6 다른 차원 축소 기법

그 외에도 Multidimensional Scaling, Isomap, t-SNE, Linear Discriminant Analysis 방법 등이 있다.

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.

 

챕터 7. 앙상블 학습과 랜덤 포레스트

여러 예측기로부터 예측을 수집하면 좋은 모델 하나보다 더 좋은 예측을 얻을 수 있다. 이를 앙상블 학습이라고 한다. 그 중, 결정 트리들의 앙상블을 랜덤 포레스트라고 한다.

 

7.1 투표 기반 분류기

여러 분류기 중 가장 많이 선택된 클래스를 예측하는 것을 직접 투표 (hard voting) 이라고 한다. 만약 훈련 결과가 모두 독립이라면 51%의 정확도를 가진 1000개의 분류기로 75% 정확도를 기대할 수 있다. 만약 모든 분류기가 클래스의 확률을 예측할 수 있으면, 확률을 기반으로 투표하는데 이를 간접 투표 (soft voting) 이라고 한다.

 

7.2 배깅과 페이스팅

같은 알고리즘을 사용하되 훈련 세트의 서브셋을 무작위로 구성하는 방법도 있다. 이 때 중복을 허용하면 bagging이라고 하며 중복을 허용하지 않으면 pasting 이라고 한다. 배깅과 페이스팅은 병렬로 학습할 수 있기 때문에 인기가 높다.

 

7.2.1 사이킷런의 배깅과 페이스팅

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.BaggingClassifier.html

 

sklearn.ensemble.BaggingClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org

sklearn의 BaggingClassifier나 BaggingRegressor를 사용하면 된다. 페이스팅을 사용하려면 bootstrap=False로 지정하면 된다. 앙상블은 비슷한 편향에서 더 작은 분산을 만든다. 기존에도 설명했지만 편향은 모델과 데이터간의 거리 (예측이 정확하지 않을수록 크다)이고 분산은 예측된 값들 끼리의 거리이다. (모델이 복잡할수록 크다)


7.2.2 oob 평가

BaggingClassifier는 기본적으로 중복을 허용하여 m개 샘플을 선택하는데, 이는 각각의 예측기에 평균 63% 정도만 샘플링 된다는 뜻이다. ( (1-1/m)^m ) 따라서 남은 37%는 훈련하지 않으므로 oob (out-of-bag) 샘플을 사용해 평가할 수 있다. BaggingClassifier.oob_decision_function_ 을 통해 확인할 수 있다. 각 샘플이 oob에 속한 예측기들의 예측값 평균이다. 그러한 예측기가 없을 때에는 출력되지 않는다.


7.3 랜덤 패치와 랜덤 서브스페이스

BaggingClassifier를 통해 데이터가 아니라 특성을 샘플링할 수 있다. 데이터와 특성을 모두 샘플링하는 것을 Random Patches Method라고 부르고 특성만 샘플링 하는 것은 Random Subspaces method 라고 한다.

 

7.4 랜덤 포레스트

랜덤 포레스트는 일반적으로 Bagging을 적용한 결정 트리의 앙상블이다. 전형적으로 max_samples를 훈련 세트의 크기로 지정한다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html

 

3.2.4.3.1. sklearn.ensemble.RandomForestClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

7.4.1 엑스트라 트리

랜덤 포레스트에서 각 노드는 무작위로 특성의 서브셋을 만들어 사용하지만, 더욱 무작위하게 만들기 위해 최적의 임곗값을 찾는 대신 후보 특성을 사용해 무작위로 분할한다음 최적의 분할을 선택하는 것을 Extremely Randomized Trees 라고 부른다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesClassifier.html

 

3.2.4.3.3. sklearn.ensemble.ExtraTreesClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org


7.4.2 특성 중요도

RandomForestClassifier.feature_importances_ 를 보면 각 특성의 중요도를 알 수 있다. 

 

7.5 부스팅

boosting은 약한 학습기를 여러 개 연결하여 강한 학습기를 만드는 앙상블 방벙비다.

 

7.5.1 아다부스트

이전 모델이 과소적합했던 훈련샘플들의 가중치를 높여 새로운 예측기를 만드는것이 Ada Boost 방법이다. 첫 번째 분류기가 훈련 한 후, 잘못 분류된 훈련 샘플의 가중치를 높여 두 번째 분류기를 만들고, 그렇게 n 개의 분류기를 만든다. 추후 예측을 할 때에는 각각의 분류기가 투표를 하는데, 각 샘플의 가중치에 비례하여 에러율을 정하고 에러율에 기반하여 각 분류기의 투표 가중치를 정한다.

 

사이킷런에서는 Ada Boost의 다중 클래스 버전을 사용한다. AdaBoostClassifier와 AdaBoostRegressor가 존재한다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostClassifier.html

 

sklearn.ensemble.AdaBoostClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostRegressor.html

 

sklearn.ensemble.AdaBoostRegressor — scikit-learn 0.22.1 documentation

 

scikit-learn.org


7.5.2 그래디언트 부스팅

또 다른 부스팅 방법은 Gradient Boosting이다. 이전 예측기가 만든 Residual Error에 새로운 예측기를 학습시킨다. 새로운 샘플에 대한 예측을 만들려면 모든 트리의 예측을 더하면 된다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html

 

3.2.4.3.5. sklearn.ensemble.GradientBoostingClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingRegressor.html

 

3.2.4.3.6. sklearn.ensemble.GradientBoostingRegressor — scikit-learn 0.22.1 documentation

 

scikit-learn.org

learning_rate로 각 트리의 기여 정도를 조절하는데, 낮을 수록 많은 트리가 필요하지만 성능은 좋아진다. 트리가 너무 많으면 과대적합 되므로 최적의 트리수를 찾아야 하는데 staged_predict() method를 사용하면 최적의 개수를 찾을 수 있다.

 

Gradient Boosting 과정에서 샘플을 일부만 사용할 ㅅ 있는데, 이 경우 편향이 높아지는 대신 분산이 낮아진다. 이를 Stochastic Gradient Boosting 이라고 한다.

 

7.6 스태킹

stacking은 앙상블에 속한 예측기의 예측을 가지고 투표하는 모델을 훈련시키는 것이다. 이 때 예측기의 예측을 취합하여 예측하는 최종 예측기를 blender 라고 부른다. 일반적으로 훈련 세트를 나누어, 각각의 서브셋은 한 레이어의 블렌더를 훈련시키기 위해 사용된다. Multi Layer Stacking Ensemble 모델은 마치 MLP 모델과 닮았다.

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.

 

챕터 6. 결정 트리

Decision Tree는 분류와 회귀, 다중 출력 모두 가능한 다재다능한 머신러닝 알고리즘이다.

 

6.1 결정 트리 학습과 시각화

https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html

 

sklearn.tree.DecisionTreeClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org

https://scikit-learn.org/stable/modules/generated/sklearn.tree.export_graphviz.html

 

sklearn.tree.export_graphviz — scikit-learn 0.22.1 documentation

 

scikit-learn.org

위의 두 함수를 이용하여 그래프를 정의하고, 시각화 할 수 있다.

 

6.2 예측하기

 

 

트리는 root node에서 시작하여, 각각의 node에 정해져 있는 규칙에 따라 가지를 따라 내려가고, 더 이상 child node가 없는 leaf node에 도착하면 해당 leaf에 적혀 있는 class로 분류가 된다. 각각의 노드에는 불순도가 적혀있는데, 위 tree의 경우 gini method를 사용하고 있다. 기본적으로 각각의 노드에서는 하나의 특성에 대해서 기준을 나누므로 그래프에 표시해보면 수직 혹은 수평인 기준선들이 존재한다.

 

6.3 클래스 확률 추정

leaf class에 도달하였을 때 해당 leaf의 클래스 비율을 본다면 확률 추정도 가능하다. sklearn 의 decision tree에서는 predict_proba 함수를 사용하여 알 수 있다.

 

6.4 CART 훈련 알고리즘

트리를 만들기 위해서 사이킷 런은 CART (Classification And Regression Tree) 알고리즘을 사용한다. training data를 하나의 특성, 하나의 임곗값을 이용해 두 서브셋으로 나눈다. 이 때 특성과 임곗값은 두 서브셋의 불순도에 가중치를 곱해 최소가 되도록 하는 값으로 정한다. 기본적으로는 모든 조합을 해보아야 그 순간 최적의 분할을 알 수 있다. 트리가 너무 복잡해지는 것을 막기 위해 max_depth, min_smaples_split, min_samples_leaf, min_weight_fraction_leaf, max_leaf_nodes 등을 사용하여 규제를 둘 수 있다. 자세한 것은 위에 언급한 document에서 확인할 수 있다.

 

또한 CART 알고리즘은 각 순간에서 최적의 분할을 찾기 때문에 Greedy Algorithm 이며 완전히 최적인 나무를 찾는 것은 아니지만 매우 효율적이다.

 

6.5 계산 복잡도

CART 알고리즘에서 각 노드를 분할할 때에 O(n m') 의 시간이 필요하다. 경우에 따라 다르지만 결정트리는 주로 O(log m)의 층으로 구성되어있다. 각 층에는 총 O(m) 개의 데이터가 있다고 할 수 있으므로 총 시간 복잡도는 O(n m log m) 이다.

 

정확히는, T(m) = T(a) + T(m-a) + O(n m) 의 함수를 계산하면 구할 수 있다. a가 항상 1이라면 T(m) = O(n m^2) 이지만, a가 대략 m/2라고 가정하면 T(m) = O(n m log m)이 된다.

 

6.6 지니 불순도 또는 엔트로피?

불순도를 측정하는 대표적인 두 가지 방법은 지니 불순도와 엔트로피이다. 지니 불순도는 1 - sum( p(i)^2 ) 이고, 엔트로피는 - sum ( p(i) log (p(i)) ) 이다. 지니 불순도는 빈도 높은 클래스를 고립시키는 경향이 있고 엔트로피는 조금 더 균형 잡힌 트리를 만드는 경향이 있지만, 거의 비슷하다.

 

6.7 규제 매개변수

과대적합을 피하기 위해 학습할 때 결정 트리의 자유도를 규제를 통해 제한할 필요가 있다. 

 

max_depth : 최대 깊이

min_samples_split : 분할되기 위해 노드가 가져야 하는 최소 샘플 수

min_samples_leaf : 리프 노드가 가져야 하는 최소 샘플 수

min_weight_fraction_leaf : 피트 노드가 가져야 하는 전체 샘플 수에서의 비율

max_leaf_nodes : 리프 노드의 최대 수

max_features : 분할에 사용할 특성의 최대 수

 

등이 있다. 혹은, 트리를 다 만든 후 통계적으로 검정하여 pruning 하는 방법도 존재한다.

 

6.8 회귀

결정 트리는 회귀에도 사용할 수 있다.

https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeRegressor.html

 

sklearn.tree.DecisionTreeRegressor — scikit-learn 0.22.1 documentation

 

scikit-learn.org

이는 분류와 매우 비슷하지만, leaf node에서 class 대신 값을 유추하며 불순도 최소화 대신 MSE를 최소화 한다. 마찬가지로 규제가 필요하다.

 

6.9 불안정성

트리는 사용하기 편하고 여러 용도로 사용할 수 있지만, 경계를 항상 계단모양으로 만들기 때문에 회전된 데이터에 매우 불안하며, 데이터의 작은 변화에 민감하다는 단점이 있다. 해결법은 PCA를 하여 특성을 합쳐주거나 RandomForest를 사용하는 것이다.

 

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.


챕터 5. 서포트 벡터 머신

Support Vector machine은 매우 강력하고 많은 경우에 사용할 수 있는 머신러닝 모델이다. 딥 러닝이 유행하기 전에 SVM 모델이 크게 유행했다.

 

5.1 선형 SVM 분류

SVM 분류기는 데이터들을 선형 기준으로 구분하는 것을 목적으로 한다. 이 때에, 기준 선에 가장 가까운 데이터가 최대한 멀어지도록 기준 선을 긋는다면 더 잘 그은 기준선이 될 것이다. 따라서 이를 large margin classification 이라고 부른다. margin 을 정하였는데 이 바깥쪽에 새로운 데이터가 추가된다면 전혀 영향을 끼치지 않는다. 즉 margin에 위치한 샘플에 의해 결정되므로 이런 샘플들을 support vector 라고 한다.

 

SVM은 특성의 스케일에 민감하므로 StandardScaler를 사용하여 정규화해주는 것이 좋다.

 

 

5.1.1 소프트 마진 분류

모든 샘플이 기준 선과 그 margin 밖에 있따면 이를 hard margin classifcation 이라고 한다. 하지만 데이터가 애초에 선형 구분이 되지 않는다면 하드 마진 분류는 불가능하다. 따라서 margin을 최대한 넓게 잡는 것과 margin에 대한 오류를 줄이는 것을 동시에 진행하여야 하므로 soft margin classification 문제를 풀게 된다. 두 목적 사이의 균형을 하이퍼 파라미터를 사용하여 조절할 수 있다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html

 

sklearn.svm.LinearSVC — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

혹은 SVC에서 kernel을 linear로 해도 되지만, LinearSVC가 최적화 되어있더 더 빠르다.

5.2 비선형 SVM 분류

선형적으로 분류할 수 없는 데이터를 해결하여야 한다. 기존에 언급하였던 PolynomialFeatures를 사용하여 다항 특성을 추가해주어도 된다.

 

5.2.1 다항식 커널

하지만 단순히 많은 다항 특성들을 추가하는 것은 속도를 느리게 만든다. 다행히도 SVM에서는 kernel trick 이라는 것을 사용할 수 있는데, 커널이 SVM의 발전에 핵심적으로 기여하였다. kernel trick은 실제로 다항 특성을 추가하지는 않지만 cost function 을 최적화 할 때에 함수를 변형하여 특성을 추가한 것과 같은 효과를 내는 것이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html

 

sklearn.svm.SVC — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

5.2.2 유사도 특성 추가

특성을 추가 할 때에 다항 특성 뿐만 아니라 유사도 특성을 추가하는 방법도 있다. 예를 들어, 샘플들에 대한 RBF (Radial Basis Function)을 특성으로 추가하여 활용하면 선형이 아닌 데이터도 선형으로 구분할 수 있게 된다. 하지만 이는 샘플 만큼의 특성을 추가하게 되므로 매우 비효율적이게 된다.

 

5.2.3 가우시안 RBF 커널

위의 유사도 특성도 마찬가지로 kernel trick을 사용할 수 있다. SVC에서 kernel="rbf" 를 인자로 보내면 된다.

 

5.2.4 계산 복잡도

LinearSVC와 SGDClassifier의 시간 복잡도는 O(mn) 이고, SVC의 시간 복잡도는 경우에 따라 O(m^2 n) ~ O(m^3 n) 이다. 이 때 m은 샘플의 수이고 n은 특성의 수이다. 세 모델 모두 스케일을 전처리해주어야하며 SVC의 경우에만 커널 트릭 적용이 가능하다.

 

5.3 SVM 회귀

분류 문제는 margin이 가장 큰 기준을 찾는 것이었다면 회귀 문제는 margin 안에 최대한 많은 데이터가 들어가도록 하는 것이다. 하이퍼 파라미터 C가 커질수록 마진 오차에 민감해지므로 과대적합된다. SVC와 마찬가지로 LinearSVR과 SVR 을 지원한다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVR.html

 

sklearn.svm.LinearSVR — scikit-learn 0.22.1 documentation

 

scikit-learn.org

https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVR.html

 

sklearn.svm.SVR — scikit-learn 0.22.1 documentation

 

scikit-learn.org

5.4 SVM 이론

SVM의 훈련 알고리즘은 수학적으로 어떻게 작동하는지 알아보는 단원이다. 중요한 부분이지만 블로그 특성상 식을 입력하는 것이 번거로워 간단하게 설명하겠다. 최적화 분야에 대해 잘 안다면 쉽게 넘어갈 수 있을 것이다.

 

5.4.1 결정 함수와 예측

오류를 발생시키지 않거나, 제한적인 오류를 가지며 최대한 마진을 크게 하는 기준선과 크기를 정하는 것이다. (w^t x + b <= 1)

 

5.4.2 목적 함수

w와 b의 비율은 유지하되 스케일이 바뀐다면 기준선은 그대로지만 마진의 폭이 바뀌게 된다. 즉 w가 작을수록 마진이 커지므로 w의 크기를 최소화하는 것이 중요하다. (minimize 1/2 w^t w + C * margin error)

 

5.4.3 콰드라틱 프로그래밍

이는 선형 제약 조건의 볼록 이차 최적화 문제이므로 Quadratic Programming Problem 이라고 부를 수 있다. 이런 문제를 푸는 알고리즘은 이미 존재하므로 SVM 문제를 적당히 변형하여 해당 알고리즘에 전달할 수 잇다.

 

5.4.4 쌍대 문제

최적화 분야에서는 primal problem과 dual problem이라는, 서로 대응되는 관계의 문제가 존재한다. dual problem의 해는 primal problem의 하한 (혹은 상한)이 되는데, 특정 경우에서는 하한 뿐만아니라 실제 최솟값이 된다. SVM은 이 조건을 만족하므로 dual problem을 푸는것이 primal problem을 푸는 것과 같다. SVM의 dual problem의 목적함수에는 두 데이터 간의 내적이 포함된다.

 

5.4.5 커널 SVM

dual problem을 푸는 이유는 커널 SVM을 적용할 수 있게 해주기 때문이다. 우리가 기존의 벡터를 다항 변환하여 여러 특성을 만들었다고 하자. 구체적으로 x 가 (x1, x2)일 때에 f(x)가 (x1^2, sqrt(2) x1 x2, x2^2) 인 변환 f를 생각하자. 이 때 a,b를 f(a), f(b)로 변환하면 f(a)와 f(b)의 내적값이 a와 b 내적값의 제곱이 된다. 즉 f를 생각하지 않고도 변환 후 두 점의 내적을 알 수 있다. 

 

위의 변환 f 뿐만 아니라, 다양한 변환에 대해 Kernal 함수가 주어져있다. 대표적으로 선형 커널, 다항 커널, 가우시안 RBF 커널 (무한 차원의 다항 변환과 동일), sigmoid 커널이 있다.

 

커널 함수를 이용하여 최적화 문제를 풀었다면, 예측에 이를 적용할 수 있어야 한다. 다행히도 수학적인 계산을 통하여 f변환과 마진 벡터 w, b를 모르더라도 dual problem의 해를 가지고 예측을 해낼 수 있다.

 

5.4.6 온라인 SVM

선형 SVM 분류기의 cost function을 hinge loss를 이용하여 정의한다면 경사 하강법도 적용할 수 있으므로 online SVM classifier를 정의할 수 있다.

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.


챕터 4. 모델 훈련

모델이 어떻게 작동하는지 잘 이해하면 모델 및 알고리즘 설정, 하이퍼 파라미터 변경을 적절하고 빠르게 할 수 있다.

 

4.1 선형 회귀

선형 회귀는 특성들의 선형 함수로 함수 값을 예측하며, 주로 RMSE를 최소화하는 선형 파라미터를 학습한다.

 

4.1.1 정규방정식

선형 회귀는 수학적으로 RMSE를 최소화하는 파라미터를 계산을 통해 구할 수 있다.

 

4.1.2 계산 복잡도

정규 방정식을 통해 파라미터를 구할경우 계산 복잡도는 O(n^2.4) 에서 O(n^3) 정도가 된다. 다행히도 샘플 수에는 선형적으로 증가한다. (O(m))

 

4.2 경사 하강법

Gradient Descent는 여러 종류의 문제에서 최적의 해법을 찾을 수 있는 매우 일반적인 최적화 알고리즘이다. 핵심 아이디어는 Cost Function을 최소화하기위해 함수를 미분하여 파라미터를 조정하는 것이다. 이 때에 learning late가 중요한데 너무 작거나 크면 안된다. 또한 Gradient Descent는 해를 local minimum으로 수렴하게 만드는 경우가 있는데 함수가 Convex일 경우 local minimum은 항상 global minimum이다.

 

경사 하강법을 사용할 때에는 값들을 정규화해 주는 것이 훨씬 효율적이다.

 

4.2.1 배치 경사 하강법

MSE 값을 각각의 파라미터로 미분한 후, 해당 방향으로 learning late를 곱하여 감소시켜주는 것이 배치 경사 하강법이다. 이 때, 모든 train data에 해당하는 MSE 값을 최소화하게 된다. learning late를 적당히 조절하여 학습 하는 것이 중요하다. 반복 횟수는 변화 값이 어느 수준 이하가 될 때까지 반복하는 것이 좋다.

 

4.2.2 확률적 경사 하강법

배치 경사 하강법에서는 모든 데이터를 사용하여 그래디언트를 계산하기 때문에 계산량이 많고 속도가 느리다. 반대로 확률적 경사 하강법은 매 스텝에서 딱 한개의 샘플을 무작위로 선택하여 그래디언트를 계산하는 것이다. 이는 계산을 매우 빠르게 만들어 준다. 하지만 학습을 반복한다면 마지막에 수렴하지 않는 모습을 보일 수 있으므로, 학습률을 점점 줄이는 것이 좋은 해결법 중 하나이다. 이를 학습 스케쥴링이라고 한다.

 

4.2.3 미니배치 경사 하강법

미니배치 경사 하강법은 하나의 샘플을 기반으로 그래디언트를 계산하는 것이 아니라 미니배치라 부르는 샘플 세트에 대해 계산하는 것이다. 

 

4.3 다항 회귀

데이터가 선형보다 복잡한 형태여도 선형 회귀를 사용할 수 있는데, 각 특성의 거듭 제곱을 특성으로 포함하여 선형 회귀를 학습시키면 된다. 직접 특성을 추가하여도 되지만 sklearn의 PolynomialFeatures를 사용할 수 있다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html

 

sklearn.preprocessing.PolynomialFeatures — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

4.4 학습 곡선

고차 다항 회귀를 적용하면 기존의 선형 회귀 보다 훨씬 더 훈련 데이터에 잘 맞추려 할 것이다. 하지만 이는 훈련데이터에 과대적합 되는 모델이다. 그렇다고 선형 회귀를 사용하면 과소적합이 된다. 따라서 적당한 차수의 다항 회귀를 사용하여야 하는데, 학습 곡선을 그려보면 도움이 될 것이다.

 

 

좌측은 과소적합의 학습 곡선이고 우측은 과대적합의 학습 곡선이다.

과소 적합의 경우 두 곡선이 높은 오차에서 평행하게 된다. 훈련은 잘 했지만 모델 자체가 오차를 줄일 수 없기 때문이다. 과대적합의 경우 훈련 데이터의 오차가 작아지는데 검증 데이터의 오차와 차이가 있다.

 

오차는 세 가지 다른 종류의 오차의 합으로 표현된다.

 

- 편향 : 편향은 잘못된 가정에 의한 것으로 훈련 데이터에 과소 적합되기 쉽다.

- 분산 : 분산은 데이터의 작은 변동에 모델이 민감하게 반응하기 때문에 일어나는 것으로 과대적합 되기 쉽다.

- 줄일 수 없는 오차 : 줄일 수 없는 오차는 데이터 자체의 노이즈 때문에 발생하는 것으로 노이즈를 제거하는게 유일한 해결법이다.

 

4.5 규제가 있는 선형 모델

모델에 제한을 두어 규제하면 과대적합을 피할 수 있다.

 

4.5.1 릿지 회귀

훈련하는 동안 모델의 파라미터 크기에 제한을 두면 가중치가 작게 유지되도록 노력하여 과대적합을 피할 수 있다. 릿지 회귀는 비용함수에 파라미터 제곱에 비례한 값을 추가하는 것이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html

 

sklearn.linear_model.Ridge — scikit-learn 0.22.1 documentation

 

scikit-learn.org

위 모델을 이용하여 학습하거나, SGD Classifier에서 'l2' penalty를 추가하면 된다.

 

4.5.2 라쏘 회귀

라쏘 회귀는 릿지 회귀와 비슷하지만 파라미터 제곱이 아닌 파라미터 절댓값에 비례한 비용을 추가하는 것이다. 릿지 회귀는 가중치가 원점에 가까이 가려고 한다면 라쏘 회귀는 필요없는 가중치를 완전히 제거하려는 특성을 가진다. 특정 곡선이 원에 접하는 점을 찾는 경우와, 다이아몬드에 접하는 점을 찾는 경우를 비교해보면 될 것이다.

 

라쏘 회귀의 그래디언트는 0에서 미분 불가능 하므로 0일때 미분값이 0으로 주어지는 서브그래디언트 벡터를 사용하면 된다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html

 

sklearn.linear_model.Lasso — scikit-learn 0.22.1 documentation

 

scikit-learn.org

마찬가지로 'l1' penalty를 추가한 SGD Classifier를 사용할 수 있다.

 

4.5.3 엘라스틱넷

엘라스틱 넷은 릿지 회귀와 라쏘 회귀를 절충한 모델으로, 비용함수의 두 가중치를 특정 비율로 섞으면 된다. 라쏘 회귀는 가끔 문제를 일으키므로 이 경우에 엘라스틱넷을 사용하면 될 것이다.

 

4.5.4 조기 종료

반복 횟수에 따라 훈련 세트의 RMSE는 줄어들 가능성이 높지만 검증 세트에 대한 RMSE는 과대적합시 증가할 가능성이 높으므로 검증 세트에 대한 RMSE가 다시 증가하려는 추세가 보일 때 학습을 중지하는 것이 좋다. 이를 early stopping 이라고 한다.

 

4.6 로지스틱 회귀

회귀 알고리즘을 사용하여 분류 모델을 만드는 것을 Logistic Regression 이라고 한다.

 

4.6.1 확률 추정

선형 회귀의 값이 주어졌다면, 이를 sigmoid function에 대입하여 0과 1사이의 확률로 변환하는 것을 로지스틱 회귀 모델이라고 한다. 이 값이 0.5 (혹은 다른 기준) 보다 크다면 분류 함수에서는 양성 클래스로 예측하면 된다.

 

4.6.2 훈련과 비용 함수

따라서 양성 샘플의 경우 logit의 값이 크고, 음성 샘플의 경우 logit의 값이 작도록 모델을 학습해야 한다.

 

비용함수는 y=1일 때 -log(p), y=0일 때 -log(1-p)인 함수를 사용한다. 이를 하나의 식으로 표현하려면 - y log (p) - (1-y) log (1-p) 와 같이 표기하면 된다. 이 함수는 미분 가능하므로 경사 하강법 알고리즘을 적용하여 학습할 수 있다.

 

4.6.3 결정 경계

로지스틱 회귀를 이용하여 추측된 양성 확률이 0.5보다 크다면 양성 확률이 음성 확률보다 크다는 뜻이므로 양성 클래스로 예측하게 된다. 로지스틱 회귀도 선형 회귀를 기반으로 작동하기 때문에 그래프에서의 경계가 선형으로 나타난다. 로지스텍 회귀 모델도 패널티를 적용할 수 있다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html

 

sklearn.linear_model.LogisticRegression — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

4.6.4 소프트맥스 회귀

여러 개의 binary classifier를 사용하지 않고 하나의 회귀 모델으로 다중 클래스를 분류할 수 있다. 이를 Softmax Regression 혹은 Multinomial Logistic Regression 이라고 한다.

각 클래스 k에 대해 로지스틱 회귀 모델을 학습 한 후, 각각의 회귀 값을 지수화 하여 정규화 하면 된다. 즉 식으로는

 exp(s_k(x)) / sum (exp(s_k(x)) 가 된다. 이 값들의 합은 1이 되므로 각각을 확률로 볼 수 있으며, 가장 큰 확률을 가지는 클래스로 예측하면 된다.

 

이 모델의 경우 새로운 비용함수를 적용하여야 하는데 주로 cross entropy function을 사용한다. 

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.


챕터 3. 분류

 

일반적인 지도 학습 중 2장에서 회귀를 다루었다면 3장에서는 분류를 다룬다.

3.1 MNIST

머신러닝을 공부할 때 많은 경우에 MNIST 데이터셋 분류하기로 공부를 시작한다. 이 데이터셋은 7만장의 28 by 28 이미지 파일로 이루어져 있으며 각각의 이미지 파일은 0 부터 9 까지의 숫자 중 하나를 뜻한다. sklearn.datasets 에 포함되어있다.

 

데이터는 dictionary 형태로 불러와지는데 'DESCR'에 데이터 설명, 'data'와 'target'에 X와 y 데이터가 들어있다. 각각의 데이터를 (28,28)으로 reshape한 후 plot시켜보면 이미지를 확인할 수 있다. 7만개의 데이터 중 뒤의 10000개가 테스트세트로 나누어져있다.

 

3.2 이진 분류기 훈련

숫자 5를 식별하는 binary classifier를 먼저 만들어 본다. 사용할 분류 모델은 SGD (Stochasti Gradient Descent)이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html

 

sklearn.linear_model.SGDClassifier — scikit-learn 0.22.1 documentation

 

scikit-learn.org

from sklearn.linear_model import SGDClassifier

sgd_clf = SGDClassifier(max_iter=5, random_state=25)
sgd_clf.fit(X_train, y_train_5)

 

3.3 성능 측정

분류기 평가는 회귀모델 평가보다 훨씬 어렵고 다양하다.

 

3.3.1 교차 검증을 사용한 정확도 측정

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score

 

sklearn.model_selection.cross_val_score — scikit-learn 0.22.1 documentation

 

scikit-learn.org

sklearn의 cross_val_score를 이용하여 예측기의 정확도를 판단할 수 있다. 그런데 이 데이터는 숫자 5가 아닐 확률이 90%이기 때문에 단순히 accuracy를 비교하는 것은 큰 의미를 가지지 못할 수 있다.

 

3.3.2 오차 행렬

따라서 분류기의 성능을 평가 할 때에 confusion matrix를 조사하는 것이 좋은 방법이다. 

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix

 

sklearn.metrics.confusion_matrix — scikit-learn 0.22.1 documentation

 

scikit-learn.org

confusion matrix의 행은 실제 클래스를 나타내고, 열은 예측한 클래스를 나타낸다.

 

위 예제의 경우 실제로 '1' class인데 '2' class로 분류되는게 1개있음을 알 수 있다.

 

특히 binary classifier에서 false negative / false positive / true negative / true positive 라는 용어를 사용하는데, true와 false는 분류의 정답 여부이고, positive와 negative는 예측 클래스의 음성/양성이다. 실제로 양성인 클래스를 음성으로 분류했다면 false negative가 되는 것이다.

 

이를 이용한 몇 가지 지표가 더 있다.

 

정밀도 (precision) : TP / (TP + FP)

- 양성이라고 예측한 것 중 정확도

 

재현율 (recall) : TP / (TP + FN)

- 실제 양성 중 정확도

 

3.3.3 정밀도와 재현율

정밀도와 재현율 모두 높으면 좋은 지표이지만 한 쪽만 높은 것은 경우에 따라 좋지 않을 수 있다. 따라서 둘을 조화평균한 F1 Score를 사용하기도 한다.

 

하지만 경우에 따라 재현율이 높은 경우여야 할 수도있고 정밀도가 높은 경우여야 할 수도 있다. 아쉽게도 둘 모두 높이는 것은 쉽지 않으므로 한 쪽을 상대적으로 포기해야하는데, 이를 정밀도/재현율 트레이드오프 라고 한다.

 

3.3.4 정밀도/재현율 트레이드오프

SGD Classifier는 결정 함수를 사용하여 샘플의 점수를 계산하고, 특정 값을 기준으로 class를 0 또는 1로 분류한다. 따라서 이 기준을 변화시킴에 따라 정밀도와 재현율이 변화할 수 있다. 기준을 엄격하게 할 수록 재현율은 항상 감소하지만, 정밀도는 대체로 증가할 뿐 항상 증가하지는 않는다.

predict() method 대신 decision_function() method를 호출하면 샘플의 점수를 얻을 수 있다. 

 

 

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_curve.html

 

sklearn.metrics.precision_recall_curve — scikit-learn 0.22.1 documentation

 

scikit-learn.org

또한 샘플의 점수를 이용하여 precision recall curve를 그래프로 나타낼 수 있다.

 

3.3.5 ROC곡선

ROC Curve (receiver operating characteristic) 도 binary classifier에서 널리 사용하는 그래프이다. false positive rate에 대한 true positive rate의 그래프로, 실제 음성 중 양성으로 분류한 비율과 실제 양성 중 양성으로 분류한 비율의 그래프이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_curve.html

 

sklearn.metrics.roc_curve — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

ROC curve는 항상 증가함수이고, 곡선 아래의 면적(AUC)이 넓을 수록 좋은 분류기라고 할 수 있다. 완전한 랜덤 분류기의 면적은 0.5이고 가장 이상적인 분류기의 면적은 1이다. roc_auc_score 함수를 사용하면 면적을 구할 수 있다.

 

만약 RandomForestClassifier의 AUC를 구하고 싶다면, 결정 함수 값을 구해야 하는데 랜덤포레스트 분류기의 경우 predict_proba() 로 분류 확률을 구하는 것이 좋다.

 

 

3.4 다중 분류

multiclass classifier는 여러 개의 class 중 하나로 구별하는 것이다. 이는 binary classifier로도 구현할 수 있는데, 숫자 별 이진분류기 10개를 훈련시켜 가장 높은 결정 점수를 클래스로 선택하는 방법이 OvA 전략이고, 서로 다른 두 숫자로 구별하는 이진분류기 45개를 훈련시켜 투표하는 방법이 OvO 전략이다. OvO 전략의 분류기 개수는 많지만 한 분류에 해당하는 데이터가 작다는 특징이 있다.

 

다중 클래스 분류 작업에 이진 분류 알고리즘을 선택하면 사이킷런이 자동으로 감지해 OvA 혹은 OvO를 적용한다. 다중 클래스 분류의 경우에도 사용하는 method는 거의 동일하다.

 

3.5 에러 분석

가능성이 높은 모델을 찾은 후 모델의 성능을 개선하는 방법 중 하나는 에러의 종류를 분석하는 것이다.

confusion matrix를 만든 후 이미지로 표현하면 어느 경우에 오차가 많이 나는지 시각화 할 수 있다. 이 때에 각 값을 행의 합으로 나눈 후 대각선을 제외하고 이미지로 표현하면 에러 비율을 더 잘 시각화할 수 있다. MNIST에서 8과 9의 경우 분류가 잘 안되고 있음을 알 수 있고, 3과 5가 서로 혼돈된다는 점을 알 수 있다. 실제로 3과 5의 이미지들을 표현해보면 구분하기 힘들어보이는데, 선형 모델인 SGD를 사용하여 이 점이 부각된 것이다.

 

 

3.6 다중 레이블 분류

multilabel classification은 얼굴 인식 분류기와 같이, 여러 개의 binary label을 출력하는 분류 문제이다. f1_score를 구할 때를 제외하고는 대부분 비슷하다. f1_score를 구할 때 label 별 가중치를 설정할 수 있다. 

 

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html

 

sklearn.metrics.f1_score — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

3.7 다중 출력 분류

multioutput-multiclass classification 문제. 다중 레이블 분류에서 한 레이블이 다중 클래스가 될 수 있는 일반적인 문제이다. 

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.


챕터 2. 머신러닝 프로젝트 처음부터 끝까지

 

2장에서는 머신러닝 프로젝트에서 공통적으로 중요한 요소들에 대해 설명한다.

 

2.1 실제 데이터로 작업하기

인공적으로 만들어진 데이터셋 보다는 실제 데이터로 실험하는 것이 좋으며, 대표적인 데이터 저장소는 Kaggle이 있다.

https://www.kaggle.com/

 

Kaggle: Your Home for Data Science

 

www.kaggle.com

다양한 competition들도 열린다.

 

2.2 큰 그림 보기

캘리포니아 인구조사 데이터를 사용해 주택 가격 모델을 만드는 프로젝트를 예시로 설명하고 있다.

 

 

2.2.1 문제 정의

모델을 만드는 것이 최종 목적이 아니라, 모델을 이용하여 이익을 얻으려고 하는 것이 최종 목표이다. 따라서 프로젝트의 최종 목적 혹은 비즈니스 관계자와 소통하여 현 상황 및 최종 목표를 구체화하는것이 중요하다. 

이 문제는 레이블된 훈련 샘플이 있으니 지도 학습이며 회귀 문제이다. 또한 예측에 사용할 특성이 다수이므로 다변량 회귀문제이다.

 

2.2.2 성능 측정 지표 선택

프로젝트를 잘 해결하였는가의 척도가 필요하다. 회귀에서 자주 사용하는 지표는 RMSE이다. 그 외에도 다양한 지표가 있으며 (MAE, Euclidean norm, Manhattan norm 등)

https://scikit-learn.org/stable/modules/model_evaluation.html#regression-metrics

 

3.3. Metrics and scoring: quantifying the quality of predictions — scikit-learn 0.22.1 documentation

3.3. Metrics and scoring: quantifying the quality of predictions There are 3 different APIs for evaluating the quality of a model’s predictions: Finally, Dummy estimators are useful to get a baseline value of those metrics for random predictions. 3.3.1. Th

scikit-learn.org

위 링크에서 확인할 수 있다.

 

2.2.3 가정 검사

마지막으로 지금까지의 가정을 나열하고 검사하는 것이 좋다. 모델의 결과가 추후에 어떻게 활용되는지 정확하게 알 수 있다면 더 유용한 모델을 만들 수 있을 것이다.

2.3 데이터 가져오기

python과 scikit-learn을 사용하기 위한 준비 단계로, 간단하게만 정리하겠다.

 

2.3.1 작업 환경 만들기

http://www.python.org 

 

Welcome to Python.org

The official home of the Python Programming Language

www.python.org

파이썬을 설치 후, 가상 환경을 만들고 패키지들을 설치해야한다. 윈도우에서는 linux (ubuntu)를 사용하는 것을 추천한다. 파이썬 가상 환경에 관해서는 추후 포스팅 하겠다.

 

pip3 install --upgrade pip
pip3 install --upgrade jupyter matplotlib numpy pandas scipy scikit-learn

혹은 anaconda를 설치하여 유용한 패키지들을 한 번에 설치할 수 있다.

 

2.3.2 데이터 다운로드

comma로 데이터들이 분리되어있는 csv 파일을 많이 사용하며 urllib 라이브러리를 이용하여 웹에서 파일을 다운로드 받을 수 있다. pandas 의 read_csv 를 이용하면 된다.

 

import os
import pandas as pd

csv_path = os.path.join (housing_path, "housing.csv")
df = pd.read_csv (csv_path)

 

2.3.3 데이터 구조 훑어보기

데이터 구조를 알아볼 수 있는 몇 가지 방법을 소개한다.

 

df.head() # 처음 다섯 행 확인

df.info() # 간략한 설명, 전체 행 수, 각 특성의 데이터 타입과 값의 개수 확인

df["rooms"].value_counts() # 특성의 카테고리 count

df.describe() # 숫자형 특성들의 통계적 정보

import matplotlib.pyplot as plt

df.hist(bins=50, figsize=(20,15))
plt.show #숫자형 특성들에 대한 히스토그램

 

2.3.4 테스트 세트 만들기

데이터 구조를 훑어볼 때에 테스트 세트를 분리한 후 구조를 훑어보아야 한다. 테스트 세트가 가지고 있는 특성이 모델에 반영되면 안되기 때문이다. 그런 현상을 data snooping 편향이라고 한다.

 

테스트 세트를 직접 분리하는 방법으로는 numpy의 random.permutation을 사용하는 방법이 있다. numpy의 random.seed를 설정하면 같은 데이터 셋에서 항상 같은 테스트 세트가 추출되지만, 만약 데이터 셋이 조금 추가된다면 테스트 세트가 완전히 바뀌게 된다. 이런 경우 각각의 데이터에 대해 id를 부여하여 hash 값으로 분리하는 방법이 있다.

 

sklearn의 train_test_split을 쓰는 방법이 매우 간편하다.

 

from sklean.model_selection import train_test_split

train_set, test_set = train_test_split (df, test_size = 0.2, random_state = 25)

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

 

sklearn.model_selection.train_test_split — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

완전히 무작위로 테스트 셋을 추출하는 과정은 데이터가 많을 때에는 좋지만, 적을 때에는 우연히 편향된 테스트 셋이 추출될 가능성도 있다. 카테고리 별로 최대한 균일하게 테스트 셋을 추출하고 싶을 때에는 sklearn의 StratifiedShuffleSplit을 사용하면 된다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedShuffleSplit.html

 

sklearn.model_selection.StratifiedShuffleSplit — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

2.4 데이터 이해를 위한 탐색과 시각화

2.4.1 지리적 데이터 시각화

본 프로젝트에서 사용하는 캘리포니아 인구조사 데이터를 위도와 경도에 따라 시각화 하는 방법들을 소개한다.

 

df.plot(kind="scatter", x="longitude", y="latitude") # 단순히 그래프에 위치 표시

df.plot(kind="scatter", x="longitude", y="latitude", alpha=0.1) # 투명도를 조절하여 밀집된 지역 파악 가능

df.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4, s=df["population"]/100, label="population", figsize=(10,7), c="median_house_value", cmap=plt.get_cmap("jet"), colorbar=True, sharex=False) # cmap을 활용하여 특성에 따라 색을 변화

 

2.4.2 상관관계 조사

모든 특성 간의 표준 상관계수를 corr() method를 이용하여 계산할 수 있다.

 

corr_matrix = df.corr()

corr_matrix["median_house_value"].sort_values(ascending=False)

 

특성 사이의 상관관계를 산점도로 확인하려면 pandas의 scatter_matrix 함수를 사용하면 된다.

 

from pandas.plotting import scatter_matrix

attributes = ["median_house_value", "median_income", "total_rooms", "housing_median_age"]
scatter_matrix(df[attributes], figsize=(12,8))

 

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.plotting.scatter_matrix.html

 

pandas.plotting.scatter_matrix — pandas 0.25.3 documentation

Parameters: frame : DataFrame alpha : float, optional amount of transparency applied figsize : (float,float), optional a tuple (width, height) in inches ax : Matplotlib axis object, optional grid : bool, optional setting this to True will show the grid dia

pandas.pydata.org

 

2.4.3 특성 조합으로 실험

데이터의 특성을 그대로 사용하지 않고, 특성 사이의 상관관계를 활용하거나 새로운 특성을 판단하에 만들어서 사용하는 것이 더 좋은 모델을 만드는 경우가 될 수 있다. 이러한 판단을 하기 위해서는 데이터를 분석하고 시각화하는 과정을 반복하여 통찰을 얻어야한다.

2.5 머신러닝 알고리즘을 위한 데이터 준비

데이터 전처리를 수동으로 하는 것 보다는 함수로 만들어 자동화하는 것이 좋다. 데이터셋에 변화가 있어도 쉽게 재적용할 수 있으며 실제 모델 예측에 활용하거나 여러 조합을 시도해 보는데에 훨씬 유리하다.

 

2.5.1 데이터 정제

데이터에 누락된 값이 있는 경우 drop, dropna, fillna 등의 method를 이용하여 처리할 수 있다. 만약 fillna를 사용하여 중간값 등으로 채워넣는 경우 모델 학습시의 중간값을 기억하여야 추후 테스트 데이터에도 해당 값을 사용할 수 있다. 이러한 과정을 자동으로 해주는 것이 sklearn의 SimpleImputer 이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html

 

sklearn.impute.SimpleImputer — scikit-learn 0.22.1 documentation

 

scikit-learn.org

from sklearn.impute import SimpleImputer

imputer = SimpleImputer(strategy="median")

imputer.fit(df) # df에 수치형 자료만 있다고 가정

print (imputer.statistics_)

X = imputer.transform(df)

 

이 과정에서 사이킷런의 설계 철학을 알아볼 필요가 있다.

 

https://arxiv.org/pdf/1309.0238v1.pdf

불러오는 중입니다...

일관성 : 모든 객체가 일관되고 단순한 인터페이스를 공유한다.

검사 가능 : 모든 추정기의 하이퍼파라미터는 직접 접근할 수 있다.

클래스 남용 방지 : 데이터 셋을 항상 numpy array나 sparse matrix로 표현한다.

조합성 : 기존의 구성요소를 최대한 재사용 한다. (pipeline)

합리적인 기본값 : 대부분의 파라미터들이 합리적인 default를 가지고 있다.

 

특히 일관성 부분에서, 객체들은

- estimator (데이터 셋을 기반으로 parameter 들을 추정, fit method)

- transformer (estimator 중 데이터를 변환, transform method, fit_transform method)

- predictor (estimator 중 predict가 가능 한 것. predict method, score method 등)

중 하나의 종류로 이루어져 있다.

 

2.5.2 텍스트와 범주형 특성 다루기

텍스트와 범주형 특성은 수치화하여 모델링 할 필요가 있다. 예를들어 pandas factorize() method를 사용하면 각각의 카테고리를 정수로 매핑해준다. 하지만 이런 매핑은 수의 크기관계가 생겨나므로 사용할 수 없는 경우가 있다. 그런 경우에는 카테고리별 이진 특성을 만드는 one-hot encoding을 추가로 사용한다.

 

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.factorize.html

 

pandas.factorize — pandas 0.25.3 documentation

Returns: labels : ndarray An integer ndarray that’s an indexer into uniques. uniques.take(labels) will have the same values as values. uniques : ndarray, Index, or Categorical The unique valid values. When values is Categorical, uniques is a Categorical. W

pandas.pydata.org

https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

 

sklearn.preprocessing.OneHotEncoder — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

책에는 언급되어있지 않지만 pandas의 get_dummies 함수를 활용하여도 된다.

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html

 

pandas.get_dummies — pandas 0.25.3 documentation

Parameters: data : array-like, Series, or DataFrame Data of which to get dummy indicators. prefix : str, list of str, or dict of str, default None String to append DataFrame column names. Pass a list with length equal to the number of columns when calling

pandas.pydata.org

 

2.5.3 나만의 변환기

sklearn에 많은 변환기들이 제공되어있지만, customized 변환기가 필요하다면 직접 fit(), transform(), fit_transform() method가 구현된 클래스를 만들면 된다. 이 때 duck typing을 지원하므로 상속할 필요는 없다. 혹은 BaseEstimator를 상속하여 활용하여도 된다. TransformerMixin을 상속하면 fit_transform() 함수도 자동으로 선언된다.

 

2.5.4 특성 스케일링

여러 학습 방법에서 특성의 스케일링이 중요하다. 주로 min-max scaling이나 standardization 방법을 사용한다. min-max scaling은 최대 최소값을 기준으로 모든 값을 0에서 1로 변환하는 것이고, standardization은 평균이 0이고 표준편차가 1인 분포로 변환시키는 것이다. 두 변환 모두 train data에서 parameter를 결정한 후 test data에 해당 값을 적용 하여야 한다.

 

2.5.5 변환 파이프라인

여러 단계의 변환을 정확한 순서대로 처리할 수 있도록 도와주는 sklearn의 Pipeline 클래스가 존재한다.

https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html

 

sklearn.pipeline.Pipeline — scikit-learn 0.22.1 documentation

 

scikit-learn.org

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

num_pipeline = Pipeline([
  ('imputer', SimpleImputer(strategy="median")),
  ('attribs_adder', CombinedAttributesAdder()),
  ('std_scaler', StandardScaler()),
])

df_tr = num_pipeline.fit_transform(df)

 

여러 개의 pipeline (수치형 pipeline과 범주형 pipeline 등) 을 합치려면 sklearn FeatureUnion 을 사용하면 된다.

https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.FeatureUnion.html

 

sklearn.pipeline.FeatureUnion — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

from sklearn.pipeline import FeatureUnion

full_pipeline = FeatureUnion(transformer_list=[
  ("num_pipeline", num_pipeline),
  ("cat_pipeline", cat_pipeline),
])


df_prepared = full_pipeline.fit_transform(df)

 

2.6 모델 선택과 훈련

2.6.1 훈련 세트에서 훈련하고 평가하기

위에서 전처리한 데이터를 가지고 여러 모델을 활용하여 데이터를 학습시키고 평가 할 수 있다. LinearRegression 등의 모델을 fit method로 훈련시키고 predict method로 얻은 예측 값과 실제 값의 RMSE를 구함으로 평가할 수 있다. 그런데 train data를 평가해보면 오차가 0.0이 나올 수 있다. 이런 경우 데이터에 과대적합한 것으로, 모델 검증에 활용할 validation data를 만들어야 한다. (test data는 정말 마지막에 사용)

 

2.6.2 교차 검증을 사용한 평가

train data를 다시 train_test_split 하여 validation data를 만들어, validation data로 모델을 평가해야한다. 주어진 데이터를 최대한으로 활용하기 위해서는 cross-validation 기법을 활용하여 데이터를 분할 후 번갈아 가며 validation data로 사용한다. 

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html

 

sklearn.model_selection.cross_val_score — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

2.7 모델 세부 튜닝

모델의 후보를 몇 가지 정한 후에, 어떤 모델을 어떤 파라미터로 사용하는 것이 가장 좋은지 판단하여야 한다.

 

2.7.1 그리드 탐색

모든 파라미터 조합을 시도해보는 과정을 도와주는 sklearn의 GridSearchCV를 사용하자.

 

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html

 

sklearn.model_selection.GridSearchCV — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

 best_params_, best_estimator_ 를 사용하여 최적의 조합 및 추정기를 확인할 수 있다. 또한 cv_results_ 를 통해 결과를 볼 수 있다.

 

2.7.2 랜덤 탐색

탐색 공간이 커지면 모든 경우를 확인할 수 없으므로 RandomizedSearchCV를 사용하여 효율적인 탐색을 할 수 있다.

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html

 

sklearn.model_selection.RandomizedSearchCV — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

2.7.3 앙상블 방법

더 좋은 모델을 활용하거나 모델의 그룹을 활용하면 더 나은 모델을 만들 수 있다. (RandomForest 등)

 

2.7.4 최상의 모델과 오차 분석

최상의 모델을 분석하면 좋은 insight를 얻을 가능성이 높다. 예를 들어 RandomForest의 중요한 features를 확인하는 방법이 있다.

 

2.7.5 테스트 세트로 시스템 평가하기

validation data를 이용하여 최적의 모델을 찾았으면 test data를 pipeline에 통과시킨 후 시스템의 최종 점수를 구할 수 있다. validation data에 최적화 된 모델이므로 이보다는 점수가 낮을 가능성이 높다.

 

2.8 론칭, 모니터링, 그리고 시스템 유지 보수

프로젝트를 완료하였다면 실제 데이터 소스를 모델에 연결하고 시스템 성능을 자동으로 체크하며 입력 데이터 및 출력 값의 품질을 자주 모니터링 해야한다. 또한 꾸준히 모델을 훈련시켜야 한다. 위의 과정을 최대한 자동화하여야 유지 보수가 편하다.

 

2.9 직접 해보세요!

위의 내용을 Kaggle 등을 통해 직접 프로젝트를 구현해 보는 것이 실력 향상에 가장 도움이 된다.

 

 

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다. 

 

챕터 1. 한눈에 보는 머신 러닝

 

1장에서는 전반적인 머신러닝의 정의와 종류에 대해 언급한다. 짧게 짧게 짚고 넘어가겠다.

 

1.1 머신러닝이란?

머신러닝은 데이터로부터 학습하도록 컴퓨터를 프로그래밍 하는 것이다.

또한 어떤 작업에서 경험을 통해 성능을 향상 시키는 과정이다.

 

1.2 왜 머신러닝을 사용하는가?

전통적인 접근 방법으로 스팸 필터링을 한다면 수동적이며 데이터의 변화에 적응하지 못한다.

반면 머신러닝 기반으로 필터링을 한다면 데이터의 업데이트에 따라 필터 알고리즘이 바뀌며 자동화된다.

또한 사람이 알 수 없는 규칙을 찾아낼 수도 있는데 이 것이 데이터 마이닝이다.

많은 수동 조정과 규칙이 필요했던 문제 / 전통적으로는 해결할 수 없는 문제 / 유동적으로 데이터에 적응하면 좋은 문제 등에 머신러닝을 활용하면 좋다.

 

1.3 머신러닝 시스템의 종류

(지도 / 비지도 / 준지도 /강화학습)

(온라인 학습 / 배치 학습)

(사례 기반 학습 / 모델 기반 학습)

 

크게 위의 세 가지 기준으로 분류 가능하다.

 

1.3.1 지도 학습과 비지도 학습

 

지도학습 : 훈련 데이터에 레이블이 있는 것. Classification, Regression 등이 있다.

비지도학습 : 훈련 데이터에 레이블이 없는 것. Clustering, Visualization, Rule mining 등이 있다.

준지도학습 : 일부 훈련 데이터에만 레이블이 있는 것. 구글의 포토 호스팅 서비스 등이 있다.

강화 학습 : 환경을 관찰해서 행동을 실행하고 보상을 받는 정책 (전략)을 학습. 대표적으로 알파고가 강화 학습이다.

 

1.3.2 배치 학습과 온라인 학습

 

배치학습 : 한번에 모든 훈련데이터로 학습 하는 것.

온라인 학습 : 데이터를 순차적으로 미니배치 단위로 학습하는 것. 정확히는 incremental learning 을 설명하려고 한 것 같다. 빠르게 변화하는 데이터를 학습할 때에 좋으며 learning late를 잘 정의하여 사용하여야 한다.

 

1.3.3 사례 기반 학습과 모델 기반 학습

 

사례 기반 학습 : KNN 등 훈련 데이터들 간의 similarity를 기반으로 학습 하는 것.

모델 기반 학습 : 훈련 데이터로 부터 모델을 만들어 학습하는 것. 모델의 종류 및 파라미터를 학습하며 학습이 얼마나 잘 되었는가는 cost function을 이용하여 판단한다.

 

1.4 머신러닝의 주요 도전 과제

머신러닝을 하며 해결해야 하는 과제들에 대해 논한다.

 

1.4.1 충분하지 않은 양의 훈련 데이터

 

알고리즘을 잘 만드는 것과 더불어 데이터의 양이 많은 것은 큰 도움이 된다.

 

1.4.2 대표성 없는 훈련 데이터

 

sampling noise : 샘플이 작아서 우연히 대표성이 없는 것

sampling bias : 표본 추출 방법이 잘못되어 대표성이 없는 것

 

위의 두 가지만 알고 넘어가자.

 

1.4.3 낮은 품질의 데이터

 

에러나 outlier를 잘 걸러낸 후 학습해야 한다.

 

1.4.4 관련 없는 특성

 

가장 의미있는 특성을 선택하고 추후 나올 PCA등을 이용하여 특성을 결합하여 해결한다.

 

1.4.5 훈련 데이터 과대적합

 

훈련 데이터에 너무 잘 맞아서 일반성이 떨어지는 경우로 모델에 제약을 가하여 regularization 하거나 더 간단한 모델을 사용해야 한다.

 

1.4.6 훈련 데이터 과소적합

 

과대적합의 반대로 더 강력한 모델을 사용하거나 제약을 줄이는 등의 해결 방안이 있다.

 

1.4.7 한걸음 물러서서

 

지금까지의 내용을 요약하여 설명되어 있다. 

1.5 테스트와 검증

데이터를 training data와 test data로 나누어 training data 로 학습 후 test data로 평가한다. 그러나 모델의 여러 hyper parameter를 설정해보며 가장 학습이 잘 되는 모델로 골라야 하므로, 이 과정에서는 validation data로 평가한다. 최종적으로 hyper parameter를 모두 결정하면, 그제서야 test data로 테스트해보면 된다. 데이터를 최대로 활용하려면 cross-validation 기법을 사용하여 training과 validation data를 번갈아 사용한다.

+ Recent posts