ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Keras] 튜토리얼7 - 데이터 자르기(train_test_split)
    💫 Computer Science/Python & AI Framework 2019. 12. 20. 16:20

    지난 포스팅에서 데이터를 train, test, validation으로 나누는 것이 성능에 좋다는 내용을 포스팅 하였습니다.

     

    2019/12/19 - [SW개발/Python Keras] - [케라스] 무작정 튜토리얼6 - train, test, validation DATA

     

    [케라스] 무작정 튜토리얼6 - train, test, validation DATA

    ● train, test, validation DATA train, test, validation data에 대한 설명 이전 포스팅 참고 2019/12/17 - [SW개발/Python Keras] - [케라스] 무작정 튜토리얼4 - RMSE, R2 (feat.회귀모델) [케라스] 무작정 튜..

    ebbnflow.tistory.com

     

     

     

     

    오늘은 데이터를 train, test, validation으로 분할하는 기법에 대해 알아보겠습니다.

     

     

    ● Slice Notation 사용

    첫번째 방법으로, python 내장함수인 slice notation을 사용하여 데이터를 자를 수 있습니다.

    slice는 start:stop[:step]의 형식으로 쓸 수있습니다. 여기서 [:step]은 써도 되고 안써도 된다는 의미입니다.

    step을 명시하지 않을 경우에는

    1. a[start:end] # start부터 end-1까지의 item
    2. a[start:] # start부터 리스트 끝까지 item
    3. a[:end] # 처음부터 end-1까지의 item
    4. a[:] # 리스트의 모든 item

    step value를 쓰는 경우에는

    1. a[start:end:step] # start부터 end-1까지 step만큼 인덱스 증가시키면서

    step을 지정할 때 :end에 유의하세요 end는 end부터 포함시키지 않겠다는 의미이지 end가 꼭 포함된다는 의미는 아닙니다.

     start나 end가 음수가 음수인 경우에는 리스트의 끝에서부터 카운트하겠다는 의미입니다.

    1. a[-1] # 맨 뒤의 item
    2. a[-2:] # 맨 뒤에서부터 item2개
    3. a[:-n] # 맨 뒤의 item n개 빼고 전부

     

     

    예제 코드

    a = [10,11,12,13,14,15,16,17,18,19]
    
    print(a)
    print(a[0:1])
    print(a[0:10])
    print(a[0:20])
    print(a[0:10:2])
    print(a[:-2])
    print(a[:-30])

     

    결과

    a = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    [10]
    [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    [10, 12, 14, 16, 18]
    [10, 11, 12, 13, 14, 15, 16, 17]
    []

     

    자세한 내용 참고

     

    자 이를 이용하여 train, test, validation 데이터로 분할해보도록 하겠습니다.

     

     

    예제 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    # 1. 데이터
    import numpy as np
    = np.array(range(1,101)) # 1~100
    = np.array(range(1,101))
    print(x)
    x_train = x[:60# 1~60
    x_val = x[60:80# 61~80
    x_test = x[80:]  # 81~100
    y_train = y[:60]
    y_val = y[60:80]
    y_test = y[80:]
     
    # 2. 모델 구성
    from keras.models import Sequential
    from keras.layers import Dense
    model = Sequential()
    model.add(Dense(10, input_shape=(1, ), activation='relu'))
    model.add(Dense(10))
    model.add(Dense(8))
    model.add(Dense(1))
     
    # 3. 훈련
    model.compile(loss='mse', optimizer='adam', metrics=['mse'])
    model.fit(x_train, y_train, epochs=100, batch_size=1, validation_data=(x_val, y_val))
     
    # 4. 평가 예측
    loss, mse = model.evaluate(x_test, y_test, batch_size=1)
    print('acc : ', mse)
     
    y_predict = model.predict(x_test)
    print(y_predict)
     
    # RMSE 구하기
    from sklearn.metrics import mean_squared_error
    def RMSE(y_test, y_predict):
        return np.sqrt(mean_squared_error(y_test, y_predict))
    print('RMSE : ', RMSE(y_test, y_predict)) 
     
    # R2 구하기
    from sklearn.metrics import r2_score
    r2_y_predict = r2_score(y_test, y_predict)
    print('R2 : ', r2_y_predict)
     
    cs

     

     

    = np.array(range(1,101))

    = np.array(range(1,101))

     

    먼저 x와 y는 1부터 100까지 요소가 들어있는 리스트로 초기화하였습니다.

    x = [1, 2, 3, 4, ....100]   y = [1, 2, 3, 4, .....100]

     

    x_train = x[:60# 1~60
    x_val = x[60:80# 61~80
    x_test = x[80:]  # 81~100
    y_train = y[:60]
    y_val = y[60:80]
    y_test = y[80:]

     

    x_train은 첫번째요소부터 59번째 요소까지 자르겠다는 의미가 됩니다.

    즉, x[0]=1 부터 x[59]=60까지만 저장하게 됩니다.

    마찬가지로 x_val은 61~80, x_test는 81~100까지 저장합니다.(y도 마찬가지)

    이렇게 잘린 데이터의 비율은 train : val : test = 6 : 2 : 2

     

    결과 코드

    # RESULT
    # acc :  2.9930102755315602e-05
    # [[ 81.00475 ]
    #  [ 82.00482 ]
    #  [ 83.00489 ]
    #  [ 84.004974]
    #  [ 85.00504 ]
    #  [ 86.00512 ]
    #  [ 87.00519 ]
    #  [ 88.00527 ]
    #  [ 89.00534 ]
    #  [ 90.00541 ]
    #  [ 91.00549 ]
    #  [ 92.00556 ]
    #  [ 93.00564 ]
    #  [ 94.00572 ]
    #  [ 95.00579 ]
    #  [ 96.00587 ]
    #  [ 97.00595 ]
    #  [ 98.00601 ]
    #  [ 99.0061  ]
    #  [100.00617 ]]
    # RMSE :  0.005473257393515181
    # R2 :  0.9999990990512332

     

     

     

     

     

    ● Sklearn의 train_test_split함수 이용하기

    머신러닝과 데이터 분석 툴을 제공하는 sklearn패키지의 models에는 데이터 분할을 위한 train_test_split함수가 들어있습니다. 이를 이용하여 자르면 데이터의 크기를 고려하지 않고 비율만으로 데이터를 자를 수 있어 편리합니다.

     

    from sklearn.model_selection import train_test_split
    train_test_split(arrays, test_size, train_size, random_state, shuffle, stratify)

    - 파라미터

    arrays : 분할시킬 데이터를 입력 (Python list, Numpy array, Pandas dataframe 등..)

    test_size : 테스트 데이터셋의 비율(float)이나 갯수(int) (default = 0.25)

    train_size : 학습 데이터셋의 비율(float)이나 갯수(int) (default = test_size의 나머지)

    random_state : 데이터 분할시 셔플이 이루어지는데 이를 위한 시드값 (int나 RandomState로 입력)

    shuffle : 셔플여부설정 (default = True)

    stratify : 지정한 Data의 비율을 유지한다. 예를 들어, Label Set인 Y가 25%의 0과 75%의 1로 이루어진 Binary Set일 때, stratify=Y로 설정하면 나누어진 데이터셋들도 0과 1을 각각 25%, 75%로 유지한 채 분할된다.

     

    - Return 값

    X_train, X_test, Y_train, Y_test : arrays에 데이터와 레이블을 둘 다 넣었을 경우의 반환이며, 데이터와 레이블의 순서쌍은 유지된다.

    X_train, X_test : arrays에 레이블 없이 데이터만 넣었을 경우의 반환

     

     

    train_test_split을 이용하면 train, test set을 분리 할 수 있는 것인데, 그렇다면 validation set은 어떻게 분리해야 할까요?

     

     

    예제 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    # 1. 데이터
    import numpy as np
    = np.array(range(1,101)) # 1~100
    = np.array(range(1,101))
    print(x)
     
    from sklearn.model_selection import train_test_split
    x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=66, test_size=0.4)
    x_test, x_val, y_test, y_val = train_test_split(x_test, y_test, random_state=66, test_size=0.5)
     
    # 2. 모델 구성
    from keras.models import Sequential
    from keras.layers import Dense
    model = Sequential()
    model.add(Dense(10, input_shape=(1, ), activation='relu'))
    model.add(Dense(10))
    model.add(Dense(8))
    model.add(Dense(1))
     
    # 3. 훈련
    model.compile(loss='mse', optimizer='adam', metrics=['mse'])
    model.fit(x_train, y_train, epochs=100, batch_size=1, validation_data=(x_val, y_val))
     
    # 4. 평가 예측
    loss, mse = model.evaluate(x_test, y_test, batch_size=1)
    print('acc : ', mse)
     
    y_predict = model.predict(x_test)
    print(y_predict)
     
    # RMSE 구하기
    from sklearn.metrics import mean_squared_error
    def RMSE(y_test, y_predict):
        return np.sqrt(mean_squared_error(y_test, y_predict))
    print('RMSE : ', RMSE(y_test, y_predict)) 
     
    # R2 구하기
    from sklearn.metrics import r2_score
    r2_y_predict = r2_score(y_test, y_predict)
    print('R2 : ', r2_y_predict)
    cs

     

    x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=66, test_size=0.4)
    x_test, x_val, y_test, y_val = train_test_split(x_test, y_test, random_state=66, test_size=0.5)

     

    이렇게 두 단계로 나누어 잘라주면 됩니다. 먼저 train과 test데이터의 비율을 6:4로 나누어주고

    전체에서 0.4비율이 된 test데이터를 다시 각 0.5 비율로 validation과 test를 나누어 줍니다.

    그렇게 되면 최종 결과가 train : test : validation = 6 : 2 : 2비율이 되어 처음 예제의 slice notation을 사용한 방법과 동일한 결과를 얻게 됩니다.

     

    여기서 주의할 점은 train_size = 0.4,  test_size = 0.4 처럼 train, test 사이즈를 모두 파라미터로 주면 train_size가 적용이 됩니다.

     

     

    결과 코드

    # train_test_split()으로 분할한 데이터 값
    # print(x)
    # [  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18
    #   19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36
    #   37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54
    #   55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
    #   73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
    #   91  92  93  94  95  96  97  98  99 100]
    # print(x_train)
    # [11 87 12 38 62  2 29 37 72 47 70 23 18 56 54 31  8 68 64 90 20 96 63 79
    #  66 43 99 65 36 35 77 58 45 10 41 57 13 60 82  7  3 33 92 32 48 76 28 14
    #  40 17 97 75 98 22 91 80 78 52 61 21]
    # print(x_test)
    # [ 5 95 39 9 73 85  1 19 34 25 44 74 81 93 26 86 15 51 30 50]
    # print(x_val)
    # [ 53 59 100 42 94 84 6 24 49 55 71 4 16 46 69 67 89 27 88 83]

     

     

     

    댓글

Designed by Tistory.