ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • #15 : KT_AIVLE_SCHOOL : DX_4th : 딥러닝
    KT_AIVLE_SCHOOL_DX_4th 2023. 10. 18. 00:07

     

    이번 세션에는 4일동안 한기영 강사님과 딥러닝에 대해서 배운다.

     


    # Intro 

    딥러닝은 어찌보면 데이터분석 초급자의  Final Stage 아닐까싶다. 혹은 중급자 과정을 시작해볼까의 느낌

    설렌냐고 물어보면, 글쎄 잘 모르겠다. 

    이유는 여러가지가 있는데, 첫째, 연휴동안 너무 오래 쉬었다. 추석연휴는 무려 6일이었다.

    덕분에 살짝 설레였던 기분은 조금 가라앉았다.

    또한, 약간의  탈락 소식들을 듣고 나서 기운도 빠졌다.(이럴줄알았으면 올인안했다.)

    원래 내 계획은 매 세션이 끝나자마자, 포스팅을 한다는 공약?을 걸었는데,  2주동안 아무것도 하기 싫었던 것 같다.  

    잠시 쉬어가는 적절한 타임에 왔던 연휴였지만, 사실 나에게는 그다지 도움이 되지 않았다.

    그래도, 다른 에이블러들은 강사님이 내주신 과제도 하고, 복습도 하고, 유익한 연휴가 되었길 바란다. 


    하여튼 이번 세션인 딥러닝에서는 

    • 회귀
    • 이진 분류
    • 다중 분류
    • CNN

    을 배운다.. 

    그리고, 추가적으로 패션MNIST도 같이 다루어주셨는데, 실제로 그림판에 그림을 그려서 결과를 맞추는 다중분류 문제였다.

    그림판에 그린.. 이미지

    내쪽은 결과값이 그다지 좋지는 않았는데 (모델 성능은 좋았는데도 분류를 잘 못했다)

    그래도 이번 세션에서 재일 집중도가 높았던 시간이었다.


    딥러닝하면 제일 먼저 드는 생각은 아마도, 그럼 머신러닝과는 어떻게 다른건데? 라는 의문이 제일 먼저 들 것 같다.

    가장 큰 차이점은 역시 , compile, 가중치(파미터), 활성화함수 등이 있겠다

    딥러닝에서는 컴파일 후 학습을 하며, 학습시에는 

    • 컴터가 가중치 초기값을 랜덤으로 할당
    • 모델로 예측을 한 후 
    • loss 를 계산하고
    • 이 loss(오차)를 줄이는 방향으로 가중치를 조절해가면서
    • 반복 학습을 하게 된다.  

    위에 보이는 것처럼, Epoch는 반복하는 학습 횟수를 의미한다. 


    #1. 회귀

    1.스케일링

    딥러닝의 전처리에는 머신러닝과는 다르게 스케일링이 필수라고 한다.

    스케일링은  보통 2가지 방법이 있다.

    1). 정규화 : 모든 값을 0~1 사이의 값으로 바꿔주기

    보통은 정규화를 많이 사용한다.

    #1-1. 정규화 : 메소드 사용
    from sklearn.preprocessing import MinMaxScaler()
    scaler = MinMaxScaler()
    
    # 적용은 train set을 기준으로 
    x_train = scaler.fit_transform(x_train)
    x_val = scaler.transform(x_val)
    
    # 1-2. 정규화 : 직접 구하기
    xmin  = x_train.min()
    xmax = x_train.max()
    x_train = (x_train - xmin)/ (xmax - xmin)
    x_val = (x_val - xmin)/ (xmax - xmin)

    2). 표준화 :  모든 값을  (평균=0, 표준편차=1)로 값으로 바꿔주기

    극심한 이상치가 존재한다면 표준화를 권장한다.

    #1-1. 표준화 : 메소드 사용
    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    
    # 적용은 train set을 기준으로 
    x_train = scaler.fit_transform(x_train)
    x_val = scaler.transform(x_val)
    
    
    # 1-2. 표준화 : 직접 구하기
    xstd  = x_train.std()
    xmean = x_train.mean()
    x_train = (x_train - xmean)/ xstd
    x_val = (x_val - xmean)/ xstd

     

    2. 모델링

    가장 먼저 딥러닝 코드는 Sequential 방식으로 학습하는 것이 좋다고, 차후에 시각지능을 담당하셨던, 김건영 강사님이 말씀하셨다. 현업에서는 Functional한 방식으로 레이어를 엮고 하지만, 초보자라면 우선 구조적으로 이해하는 방식이 좋을 것 같다. 

    2-1) 기본 모델을 선언, 요약하기

    # 세션 정리 = 리소스 아끼기
    from keras.backend import clear_session
    clear_session()
    
    #모델 : Sequential 타입으로 
    from keras.models import Sequential
    from keras.layers import Dense
    
    #layer한개짜리 모델
    nfeatures = x_train.shape[1] # nfeatures는 데이터마다 몇 차원인지 다 다를 수 있다. #2차원데이터 활용중
    model = Sequential( Dense(아웃풋 노드수, input_shape=(nfeatures, )  ))
    
    # 모델 : 요약하기 
    model.summary()

    2-2) 기본 모델 컴파일 및 학습

    # 모델 컴파일 
    model.compile(optimizer='adam', loss='mse')  #회귀에서의 지표는 mse을 사용한다. 
    
    #모델 학습
    model.fit(x_train, y_train)
    
    # 모델 예측
    y_pred = model.predict(x_val)
    
    # 모델 성능 평가
    print(f'RMSE  : {mean_squared_error(y_val,y_pred,squared=False)}')
    print(f'MAE   : {mean_absolute_error(y_val,y_pred)}')
    print(f'MAPE  : {mean_absolute_percentage_error(y_val,y_pred)}')

    2-3) Layer-Dense수와 파라미터 변경

    # 여러 layers/Dense 경우 => Hiden layer 추가하는 것을 의미한다. 이때는 [  ] 리스트에 넣어서!!
    # 히든 레이어의 경우 activation 즉 활성화 함수가 필요하다. 보통 'relu' 'swish'을 많이 쓴다.

    # 1. 세션 정리 = 리소스 아끼기
    from keras.backend import clear_session
    clear_session()
    
    #2. 모델 : Sequential 타입으로 
    from keras.models import Sequential
    from keras.layers import Dense
    
    #여러 layers/Dense 경우 => Hiden layer 추가 [ ] 리스트에 넣어서!!
    # 히든 레이어의 경우는 activation이 필요하다.
    nfeatures = x_train.shape[1] 
    model = Sequential( [ Dense( 아웃풋 노드수, input_shape=(nfeatures,), activation='relu' ),
    		Dense( 아웃풋 노드수, activation='relu' )
    		Dense(1) ] ))
    
    # 모델 : 요약하기 
    model.summary()
    
    ## 조절 가능한 파라미터: epochs(반복학 학습 횟수), learning_rate(학습율)
    # 모델 컴파일 
    from keras.optimizers import Adam 
    model.compile(optimizer=Adam(learning_rate=0.1), loss='mse')
    
    #모델 학습
    model.fit(x_train, y_train, epochs=10, validation_split=0.2)
    
    # 모델 예측
    y_pred = model.predict(x_val)
    
    # 모델 성능 평가
    print(f'RMSE  : {mean_squared_error(y_val,y_pred,squared=False)}')
    print(f'MAE   : {mean_absolute_error(y_val,y_pred)}')
    print(f'MAPE  : {mean_absolute_percentage_error(y_val,y_pred)}')

    2-4) 질문

    그러면 여기서 질문이 생긴다.

     

    1>  무엇을 조절해야 하는가 ??

    Epoch=와  Adam(learning_rate= )값을 조절할 수 있다. 

    • 만약, loss가 줄어들기는 하지만, 값이 점진적으로 줄어들지 않고  변동 폭이 크면, 그때는 learning_rate를 줄여야한다.
    •  Val_loss가 줄어들었다가 다시 상승하는 것은 과적합이므로, Epoch먼저 조절하고 다시 learning_rate를 조절한다.

    한편, 오차를 최소화하는 파라미터(가중치)는 optimizer가 담당하고, 기본적으로 'Adam'을 많이 사용한다고 한다.

     

    2> 히든 레이어는 무엇을 하는 가?

    input의 feature에서 가중치를 반영하여 새로운 특징을 만들어내며, 이는  오차를 최소화 하는 방향으로 진행된다

    이것을 Feature Engineering (Feature Representation)이라고 한다.

    그런데,  히든 레이수와  노드수의 증가는 많다고 좋은것도, 적다고 좋은것도 아니다.

     

    3> 그렇다면, 내가 딥러닝을 잘 할 수 있을려면?? 

    따라서, Feature_Engineering을 잘해야 된다는 결론을 내릴 수 있는데, 역시 오직.... 반복학습이 필수 아닐까 싶었다. 

    오늘은 마침 미니프로젝트를 했는데, 한 에이블러님이 (우리반이지만...)  적어도 for와 if 문을 만번은 시행해봐야 적어도 파이썬을 알수 있지 않나 라는 말을 해주셨다... 공감한다. 


    #2. 이진 분류

    모델링에서 이진 분류는 회귀과 비교했을 때 활성화 함수, loss_function등이 차이가 있으며,

    특히, 아웃풋 Dense( Layer)에도  활성화 함수을 적용하는 부분이 큰 차이점일것이다.

    • Loss Function => 'binary_crossentropy'
    • Output Layer Activation => 'sigmoid'

    1. 모델링 

    # 1. 세션 정리 = 리소스 아끼기
    from keras.backend import clear_session
    clear_session()
    
    #2. 모델 : Sequential 타입으로 
    from keras.models import Sequential
    from keras.layers import Dense
    
    # 최종 아웃풋 레이어에 활성화 함수 가 필요하다. 이때는 sigmoid를 사용
    # 히든 레이어의 경우는 activation이 필요하다.
    nfeatures = x_train.shape[1] 
    model = Sequential( [ Dense( 아웃풋 노드수, input_shape=(nfeatures,), activation='relu' ),
    		Dense( 아웃풋 노드수, activation='relu' )
    		Dense(1, activation='sigmoid') ] ))
    
    # 모델 : 요약하기 
    model.summary()

    2. 모델 컴파일 => 이진분류로 

    # 모델 컴파일 : loss는 이진분류 
    from keras.optimizers import Adam 
    model.compile(optimizer=Adam(learning_rate=0.1), loss='binary_crossentropy')
    
    #모델 학습
    model.fit(x_train, y_train, epochs=10, validation_split=0.2)

    3. 모델 예측시 

    활성화 함수 sigmoid를 사용했으므로(값을0~1사이로 변환), 이진 분류을위해 값 변경 (값을 0 또는 1로 변환)

    # 모델 예측
    y_pred = model.predict(x_val)
    
    # 그런데, sigmoid는 0과 1사이값으로 결과가 나오므로 변경이 필요하다
    y_pred = np.where(pred>= 0.5, 1, 0)
    
    # 모델 성능 평가
    print(classification_report(y_val, pred))

    #3. 다중 분류

    모델링에서 다중분류의 경우도 활성화 함수, loss_function등이 차이가 있으며,

    • Loss Function => 'catergorical_crossentropy' 또는 'sparse_categorical_crossentropy'
      • Y의 전처리가 정수 인코딩(0,1,2,3...) => 'sparse_categorical_crossentropy'
      • # 정수 인코딩이 선행된 이후에는 # 카데코리로 변환
        from keras.utils import to_categorical
        y_data = to_categorical(data[ 'target'], 총 카테고리 수)
      • Y의 전처리가 원핫엔코딩(0000100..) => 'catergorical_crossentropy' 
    •  Output Layer Activation => 'softmax'

    Output Layer의 노드수는 y의 범주값 즉, 우리가 최종적으로 분류하게 되는 카테고리의 수와 같다.

    부가적으로 이차원 구조의 데이터 프레임의 경우에는 

    • from sklearn.preprocessing import LabelEncoder
    • from sklearn.preprocessing import OneHotEncoder

    를 사용하지만,  n차원으로 넘어가면, from keras.utils import to_categorical이 좋다고 이 다음 세션의 강사님이 언급해주셨다.


    1. 모델링 

    # 1. 세션 정리 = 리소스 아끼기
    from keras.backend import clear_session
    clear_session()
    
    #2. 모델 : Sequential 타입으로 
    from keras.models import Sequential
    from keras.layers import Dense
    
    # 최종 아웃풋 레이어에 활성화 함수로 softmax를 사용
    # 히든 레이어의 경우는 activation이 필요하다.
    nfeatures = x_train.shape[1] 
    model = Sequential( [ Dense( 아웃풋 노드수, input_shape=(nfeatures,), activation='relu' ),
    		Dense( 아웃풋 노드수, activation='relu' )
    		Dense( 최종 아웃풋 노드수, activation='softmax') ] ))
    
    # 모델 : 요약하기 
    model.summary()

    2. 모델 컴파일 => 다중분류로 

    # 모델 컴파일 : loss는 카데고리
    from keras.optimizers import Adam 
    model.compile(optimizer=Adam(learning_rate=0.1), loss='categorical_crossentropy')
    
    #모델 학습
    model.fit(x_train, y_train, epochs=10, validation_split=0.2)

    3. 모델 예측시 

    활성화 함수softmax를 사용했으므로 각 array별로 가장 큰 확률값을 가지는 숫자를 결과로 만들기

    # 모델 예측
    y_pred = model.predict(x_val)
    
    # 그런데, softmax는 카테고리에 맞을 확률값으로 결과가 나오므로 그중 가장 큰 값을 대표값으로 해야한다.
    y_pred = y_pred.argmax(axis=1)
    
    # 모델 성능 평가
    print(classification_report(y_val, y_pred))

     

     


    # 4. CNN: 언어지능 /시각지능 미리 예습

    솔직히 말하자면, CNN부터는 거의 수업시간에 집중을 하지 못했다.  계속 다른일이 겹쳐서 해결하는 것에 신경이 쏠렸거나, 연휴 기간 동안 낮밤을 바꿔생활하면서 나태해진 머리가 멍청해졌다.  또, 나름의 문예쪽 공모전도 준비하느라 틈만 나면 아이디어를 적어서 그런 것도 있다.


    우선 CNN의 딥러닝는 앞서봤던 DNN과는 조금 더 많이 복잡해졌다.

    CNN = Convolution Neural Network 

    DNN = Deep Neural Network

    신경과학쪽도 나의 주전공 분야이기 때문에, 뉴런이라던지 신경망이라던지 반가운 언어였지만, 또 어느정도는 딥러닝을 배웠던 기억이 살짝있지만(거의 가라사대),  완벽하게 와장창 다른 개념들과 코드들이었다.


    1. 모델링 구조 

    • Input_shape : N차원 구조로 늘어남
    • Conv2D : Convolutional Layer : 필터로 feature를 도출하는 과정
    • MaxPool: MaxPooling Layer : 압축과정(계속 연산을 함)
    • Flatten :  차원을 평탄화해서 다음 Dense Layer 에 연결을 도와줌

    그리고 CNN Conv2D의 경우  이미지 분석에 주로 사용한다고 한다. 

     

    2. 모델링

    이제 파라미터도, 각각의 의미를 알아두어야 이해할 수 있게 되었다 ㅜㅜ 

    2-1) Conv2d에서 

    • input_shape 
    • kernel_size= 는 filter수이며, 2차원의 형태로 Feature Map을 구성한다.
      •  kernel_size=3은 kernel_size=(3,3)이며 가로세로3*3의 2차원 데이터 필터를 의미한다.
    • padding은  데이터의 길이를 맞출때 사용을 하며 0으로 해당값을 채운다.
      • same 옵션은 기존의 이미지 size를 소실되지 않고 보존하겠금 해준다. 
    • Strides= 는  한 보폭/ 걸음을 의미하며, filter가 몇 칸씩 건너가면서 이동할 것인지를 의미한다.
      • strides=1 은 가로세로 한칸씩 이동
    • activation=  conv2d 레이어도 히든 레이어이기 떄문에, 활성화함수가 필요하다.

    2-2) MaxPooling

    • Feature_Map(출력 데이터)의  크기를 줄이거나(특정값강조), 할때 사용한다.
    • pool_size :
      • feature맵에서 최대값을 기준으로 줄이자=> 가장 큰값들을 모아서 feature_map의 사이즈를 변경함
      • 원래 feature_map이 4*4였는데,  pool_size=(2,2)로 하면,  다음 레이어에서의 feature_map사이즈는 2*2가 됨
    • strides : 생략시에는 pool_size와 동일하다.

    2-3) Flatten

    Conv2D, MaxPooling이후, Dense에 연결하기 위해서는 1차원/단일 값으로 변경해야 연산이 가능하다.

    # 1. 세션 정리 = 리소스 아끼기
    from keras.backend import clear_session
    clear_session()
    
    #2. 모델 : Sequential 타입으로 
    from keras.models import Sequential
    from keras.layers import Dense
    
    
    #                          16특징                              28*28*1 
    model = Sequential([
    	Conv2D(16, kernel_size=(3, 3), input_shape=(28, 28, 1), padding='same', strides = 1, activation='relu'), #히든레이어
        MaxPooling2D(pool_size=(2, 2), strides=2),
        Flatten(),
        Dense(10, activation='softmax')  #아웃풋 레이어
    ])
    
    # 모델 : 요약하기 
    model.summary()

     

    3. 모델 컴파일.학습.성능

    # 모델 컴파일 : loss는 카테고리
    from keras.optimizers import Adam 
    model.compile(optimizer=Adam(learning_rate=0.1), loss='sparse_categorical_crossentropy')
    
    #모델 학습
    model.fit(x_train, y_train, epochs=10, validation_split=0.2)
    
    #모델예측
    pred = model.predict(x_val)
    pred = pred.argmax(axis=1)
    
    #모델 성능 
    print(accuracy_score(y_val,pred ))
    print(confusion_matrix(y_val, pred ))
    print(classification_report(y_val, pred ))

    ## 5. RNN /LSTM

    RNN = Recurrent Nerual Network

    RNN은 주로 시퀀셜 데이터, 즉 시계열 데이터, 시간순서에 영향 받는 데이터 분석에 주로 사용한다.

    앞의 데이터가 그 다음의 데이터에 영향을 주기 때문이다.

    예를들면, 내일의 날씨, 주식의 다음날 주가 예측등이 해당 된다.

    SimpleRNN 

    • return_sequences : False는 가장 마지막의 hidden state값만 전달 / True는 출력크기 그대로 전
    from keras.layers import Dense, Flatten, SimpleRNN, LSTM
    
    #세션정리
    clear_session()
    
    # shape 3차원
    timestep = x_train.shape[1]
    nfeatures = x_train.shape[2]
    
    # 모델 설정
    model = Sequential([
        SimpleRNN( 노드수 , input_shape = (timestep, nfeatures), return_sequences = True),
        SimpleRNN(  노드수, return_sequences = True),
        Flatten(),
        Dense(16, activation='relu' ),
        Dense(1)
    ])
    #모델요약
    model.summary()
    
    #컴파일 & 학습
    model.compile(optimizer= Adam(learning_rate = 0.001 ), loss='mse')
    model.fit(x_train, y_train, epochs = 100   , validation_split=.2)
    
    #예측& 평가
    pred = model.predict(x_val)
    
    print(mean_squared_error(y_val, pred, squared=False))
    print(mean_absolute_error(y_val, pred))
    print(mean_absolute_percentage_error(y_val, pred))

     

    LSTM

    SimpleRNN에서  장기적으로 정보를 유지하는 것에 어려움을 해결/보완하해서 나온 모델

    • RNN에서 단기기억의 기울기 소실의 문제를 해결하기 위해서 사용하게 된 모델
      • RNN에서는 tanh에 영향을 안받기위해서 선 하나을 더 추가했었음.
    • LTMS은 긴 시퀀스를 더 잘 학습시키기 위해서 사용한다. => 장기기억
    • LSTM은 장기기억 라인을 추가함으로 RNN의 문제를 해결했다.

    # 과적합 방지

    from keras.callbacks import EarlyStopping
    es = EarlyStopping(monitor = 'val_loss', min_delta = 0, patience = 0)
    
    #모델 학습시에 적용한면된다. 
    model.fit(x_train, y_train, epochs = 100, validation_split = 0.2, callbacks = [es])
    #그러면 알아서 최적의? epochs만 돌고 중간에 멈춘다.
Designed by Tistory.