ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 머신러닝 06 - sklearn 알아 보기 (비지도 학습)
    빅데이터/Machine-Learning 2022. 2. 14. 23:04

    패스트캠퍼스 '직장인을 위한 파이썬 데이터분석 올인원 패키치 Online' 참조

     

     

     

     

    01 비지도 학습이란?

    • 기계 학습의 일종으로 데이터가 어떻게 구성되었는지를 알아내는 문제의 범주에 속한다. 이 방법은 지도학습 혹은 강화학습과 달리 입력값에 대한 목표치가 주어지지 않는다
    • 방법으로는 차원축소, 군집화가 있다

     

     

     

    02 차원축소

    • feature의 개수를 줄이는 것을 넘어 특징을 추출하는 역할
    • PCA, LDA, SVD 로 나뉨
    • 계산 비용을 절감하고 전반적인 데이터에 대한 이해도를 높이는 효과

     

    ▶ PCA

    • 주성분 분석(PCA)는 선형 차원 축소 기법이다. 매우 인기 있게 사용되는 차원 축소 기법 중 하나.
    • 주요 특징중 하나는 분산(variance)을 최대한 보존 한다는 점
    • 참조 블로그 (https://excelsior-cjh.tistory.com/167)

    x,y 축으로 보는게 아닌 분산을 중점으로 P1,P2를 그려 두 선을 기점으로 특징을 추출

    • 세팅시에 n_components에 1 > 면 분산을 기준으로 차원 축소, 1 < 면 해당 값을 기준으로 feature를 축소함

    * 데이터 세팅

    더보기

    from sklearn.preprocessing import StandardScaler
    from sklearn.decomposition import PCA
    from sklearn import datasets
    import pandas as pd

     

    iris = datasets.load_iris()

     

    data = iris['data']

     

    df = pd.DataFrame(data, columns=iris['feature_names'])

     

    df['target'] = iris['target']

    pca = PCA(n_components=2)
    
    # PCA전에 스탠다드스캐일러로 스캐일을 평균 0, 표준편차를1로 만들어야함
    data_scaled = StandardScaler().fit_transform(df.loc[:, 'sepal length (cm)':'petal width (cm)'])
    
    pca_data = pca.fit_transform(data_scaled)
    
    pca_data[:5] #차원을 2개로 축소했기때문에 한 값에 2값만 나옴
    array([[-2.26470281,  0.4800266 ],
           [-2.08096115, -0.67413356],
           [-2.36422905, -0.34190802],
           [-2.29938422, -0.59739451],
           [-2.38984217,  0.64683538]])
    • 시각화로 확인
    import matplotlib.pyplot as plt
    from matplotlib import cm
    import seaborn as sns
    
    %matplotlib inline
    
    plt.scatter(pca_data[:, 0], pca_data[:, 1], c=df['target']) [행 인덱스, 열 인덱스]

     

    • 1보다 낮게하여 분산 기준으로 축소
    # components > 1 하여 분산 기준으로 축소
    pca = PCA(n_components=0.99)
    
    pca_data = pca.fit_transform(data_scaled)
    
    pca_data[:5] # 분산기준으로하면 컬럼이 몇개나올지는 랜덤임
    array([[-2.26470281,  0.4800266 , -0.12770602],
           [-2.08096115, -0.67413356, -0.23460885],
           [-2.36422905, -0.34190802,  0.04420148],
           [-2.29938422, -0.59739451,  0.09129011],
           [-2.38984217,  0.64683538,  0.0157382 ]])
    • 3D로 확인
    from mpl_toolkits.mplot3d import Axes3D
    import numpy as np 
    
    fig = plt.figure(figsize=(10, 5))
    ax = fig.add_subplot(111, projection='3d') # Axe3D object
    
    sample_size = 50
    ax.scatter(pca_data[:, 0], pca_data[:, 1], pca_data[:, 2], alpha=0.6, c=df['target'])
    plt.savefig('./tmp.svg')
    plt.title("ax.plot")
    plt.show()

     

     

    ▶ LDA

    • 'Linear Discriminant Analysis'로 선형 판별 분석법으로 불린다
    • PCA와 비슷함. 클래스 분리를 최대화 하는 축을 찾기 위해 클래스 간 분산과 내부 분산의 비율을 최대화 하는 방식으로 차원을 축소함
    • PCA는 분산을 최대한 유지하는 반면, LDA는 각각의 고유 레이블이나 클래스간의 분리를 최대한 하기위해 노력함
    # LDA
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
    from sklearn.preprocessing import StandardScaler
    
    lda = LinearDiscriminantAnalysis(n_components = 2)
    
    #스탠다드스캐일러로 스캐일을 평균 0, 표준편차를1로 만들어야함
    data_scaled = StandardScaler().fit_transform(df.loc[:, 'sepal length (cm)':'petal width (cm)'])
    
    
    lda_data = lda.fit_transform(data_scaled, df['target'])
    
    lda_data[:5]
    array([[ 8.06179978,  0.30042062],
           [ 7.12868772, -0.78666043],
           [ 7.48982797, -0.26538449],
           [ 6.81320057, -0.67063107],
           [ 8.13230933,  0.51446253]])
    • 시각화
    plt.scatter(lda_data[:, 0], lda_data[:, 1], c=df['target'])

    LDA VS PCA

     

     

    ▶ SVD

    • 'Singular Value Decomposition' 으로 상품의 추천 시스템에도 활용되어지는 알고리즘 (추천시스템)
    • 특이값 분해 기법. PCA와 유사한 차원 축소 기법. scikit-learn 패키지에서는 'truncated SVD (aka LSA)'를 사용함
    from sklearn.decomposition import TruncatedSVD
    
    # 스탠다드스캐일러로 스캐일을 평균 0, 표준편차를1로 만들어야함
    data_scaled = StandardScaler().fit_transform(df.loc[:, 'sepal length (cm)':'petal width (cm)'])
    
    svd = TruncatedSVD(n_components=2)
    
    svd_data = svd.fit_transform(data_scaled, df['target'])
    
    plt.scatter(svd_data[:, 0], svd_data[:, 1], c=df['target'])

     

     

     

     

     

     

    03 군집화

    • 클러스터링으로 불리며 X값을 주면 스스로 분류를 하게 된다. 
    • K-Means/DBSCAN 으로 나뉜다

     

    ▶ K-Means

    • 중심 데이터를 찾은 후 점을 찍고 거기서 가까운 점을 찾고 거기서 다시 중간 점을 찾고 계속해서 중간 점을 찾아가면서 값을 분류 함
    • 주로 스팸 문자 분류, 뉴스 기사 분류등에 쓰인다.
    • 하이퍼파라미터 중 'max_iter'를 조절하여 군집 분포를 조절 할 수 있다.
    # K-Means
    from sklearn.cluster import KMeans
    
    #몇개의 그룹인지 모를때는 군집수를 여러번 돌려봐야함
    kmeans = KMeans(n_clusters=3)
    
    cluster_data = kmeans.fit_transform(df.loc[:, 'sepal length (cm)':'petal width (cm)'])
    
    cluster_data[:5]
    array([[3.41925061, 0.14135063, 5.0595416 ],
           [3.39857426, 0.44763825, 5.11494335],
           [3.56935666, 0.4171091 , 5.27935534],
           [3.42240962, 0.52533799, 5.15358977],
           [3.46726403, 0.18862662, 5.10433388]])
           
    kmeans.labels_
    array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2,
           2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 0, 0, 2, 2, 2, 2,
           2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 0])

     

     

    ▶ DBSCAN (Density-based spatial clustering of applications with noise)

    • 밀도가 높은 부분을 클러스터링 하는 방식
    • 어느점을 기준으로 반경 x내에 점이 n개 이상 있으면 하나의 군집으로 인식하는 방식
    • DBSCAN은 n_cluster 지정 필요 없음
    • 기하학적인 clustering도 잘 찾아냄

    from sklearn.cluster import DBSCAN
    
    # DBSCAN의 파라미터
    # eps - 샘플간의 최대 거리
    # min_sample = 몇개 이상을 그룹으로 간주 시킴
    dbscan = DBSCAN(eps=0.6, min_samples=2)
    
    # DBSCAN은 예측을 바로 시킴
    dbscan_data = dbscan.fit_predict(df.loc[:, 'sepal length (cm)':'petal width (cm)'])
    
    # 알아서 분류를 시킴
    dbscan_data
    array([ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  0,  0,  1,
            1,  1,  1,  1,  1,  1,  2,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,
            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
            1,  1,  1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  2,  1,  1,  1,
            1,  1,  1,  1, -1,  1,  1, -1,  1,  1,  1,  1,  1,  1,  1,  3,  1,
            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  1,  1,  1,  1,
            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
          dtype=int64)

     

     

    04 군집화 평가 - 실루엣 스코어

    • 클러스터링의 품질을 정량적으로 평가해주는 지표
    • 1 - 품질이 좋음
      0 - 품질이 않좋음 (클러스터링의 의미가 없음)
      음수 - 잘못 분류됨
    from sklearn.metrics import silhouette_samples, silhouette_score
    
    score = silhouette_score(data_scaled, kmeans.labels_)
    
    score
    0.44366157397640527
    
    samples = silhouette_samples(data_scaled, kmeans.labels_)
    
    samples[:5]
    array([0.73318987, 0.57783809, 0.68201014, 0.62802187, 0.72693222])
    • 시각화
    더보기

    def plot_silhouette(X, num_cluesters):
        for n_clusters in num_cluesters:
            # Create a subplot with 1 row and 2 columns
            fig, (ax1, ax2) = plt.subplots(1, 2)
            fig.set_size_inches(18, 7)

            # The 1st subplot is the silhouette plot
            # The silhouette coefficient can range from -1, 1 but in this example all
            # lie within [-0.1, 1]
            ax1.set_xlim([-0.1, 1])
            # The (n_clusters+1)*10 is for inserting blank space between silhouette
            # plots of individual clusters, to demarcate them clearly.
            ax1.set_ylim([0, len(X) + (n_clusters + 1) * 10])
        
            # Initialize the clusterer with n_clusters value and a random generator
            # seed of 10 for reproducibility.
            clusterer = KMeans(n_clusters=n_clusters, random_state=10)
            cluster_labels = clusterer.fit_predict(X)
        
            # The silhouette_score gives the average value for all the samples.
            # This gives a perspective into the density and separation of the formed
            # clusters
            silhouette_avg = silhouette_score(X, cluster_labels)
            print("For n_clusters =", n_clusters,
                  "The average silhouette_score is :", silhouette_avg)
        
            # Compute the silhouette scores for each sample
            sample_silhouette_values = silhouette_samples(X, cluster_labels)
        
            y_lower = 10
            for i in range(n_clusters):
                # Aggregate the silhouette scores for samples belonging to
                # cluster i, and sort them
                ith_cluster_silhouette_values = \
                    sample_silhouette_values[cluster_labels == i]
        
                ith_cluster_silhouette_values.sort()
        
                size_cluster_i = ith_cluster_silhouette_values.shape[0]
                y_upper = y_lower + size_cluster_i
        
                color = cm.nipy_spectral(float(i) / n_clusters)
                ax1.fill_betweenx(np.arange(y_lower, y_upper),
                                  0, ith_cluster_silhouette_values,
                                  facecolor=color, edgecolor=color, alpha=0.7)
        
                # Label the silhouette plots with their cluster numbers at the middle
                ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
        
                # Compute the new y_lower for next plot
                y_lower = y_upper + 10  # 10 for the 0 samples
        
            ax1.set_title("The silhouette plot for the various clusters.")
            ax1.set_xlabel("The silhouette coefficient values")
            ax1.set_ylabel("Cluster label")
        
            # The vertical line for average silhouette score of all the values
            ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
        
            ax1.set_yticks([])  # Clear the yaxis labels / ticks
            ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
        
            # 2nd Plot showing the actual clusters formed
            colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
            ax2.scatter(X[:, 0], X[:, 1], marker='.', s=30, lw=0, alpha=0.7,
                        c=colors, edgecolor='k')
        
            # Labeling the clusters
            centers = clusterer.cluster_centers_
            # Draw white circles at cluster centers
            ax2.scatter(centers[:, 0], centers[:, 1], marker='o',
                        c="white", alpha=1, s=200, edgecolor='k')
        
            for i, c in enumerate(centers):
                ax2.scatter(c[0], c[1], marker='$%d$' % i, alpha=1,
                            s=50, edgecolor='k')
        
            ax2.set_title("The visualization of the clustered data.")
            ax2.set_xlabel("Feature space for the 1st feature")
            ax2.set_ylabel("Feature space for the 2nd feature")
        
            plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
                          "with n_clusters = %d" % n_clusters),
                         fontsize=14, fontweight='bold')
        
            plt.show()

    plot_silhouette(data_scaled, [2,3,4,5])
    • 스캐일화가 된 데이터와 클러스터링 개수를 리스트 형태로 넣으면 된다

    빨간 점선은 평균 실루엣 계수를 의미하고 빨간점이 넘어갔으면 좋은 평가. 

    • 비교를 해보면 2개의 군집을 놓을때가 평균이 제일 높게 나온다. 즉 성능이 제일 좋다는 말

     

Designed by Tistory.