Tensorflow+Keeras에 따라 아주 간단한 이미지 분류(사과와 오렌지)

어쨌든 많이 읽어도 잘 모르겠어keras+tensorflow를 간단하게 해봤어요.이게 잘 되면 더 복잡한 문제에 도전해 봐.
이번에는 아주 간단한 애플 이미지와 오렌지색 이미지의 분류를 했다.
그림은python의 Image입니다.오픈으로 읽으면 배열이 되고, 1차원 배열로 바꾸면 Keeras에 따르면 매우 간단한 심층 학습의 예처럼 학습해 결과를 검증한다.
다음fruit.py과 같은 디렉터리에서 다음과 같이 학습용 데이터와 테스트용 데이터를 설정합니다.
./data/train/apple/(学習用りんご画像)
            /orange/(学習用オレンジ画像)

       test/apple/(テスト用りんご画像)
           /orange/(テスト用オレンジ画像)

이미지는 구글 이미지 검색에서 삭제하려고 노력한다.학습용 이미지는 각각 20장 정도, 테스트용 이미지는 각각 5장씩 상기 목록에 적절하게 선택하여 저장한다.주의해야 할 것은 학습용 이미지와 테스트용 이미지는 분리되어야 테스트를 할 수 있기 때문에 다운로드와 학습용 이미지가 다른 것을 할 수 있다.
  • 애플 이미지
  • 주황색 이미지
  • 코드는 다음과 같습니다.학습용 애플 이미지와 주황색 이미지가 담긴 디렉터리의 이미지를 하나하나 읽을 수 있는 방법은 간단하다.읽은 이미지는 [R, G, B]를 한 요소로 하는 25x25의 배열이기 때문에 거칠지만 1차원 이미지로 변환한 후 입력값을 나눈 값255.을 0~1의 값으로 학습용 모형을 먹인다.
    참고로 정답 라벨은 라벨의 값 자체가 아니라 0과 1로 구성된 배열을 바꾸어 먹는다.
    예를 들어0[1,0],1[0,1]1이 세워진 위치의 색인을 라벨의 값으로 배열하는 것이다.
    fruit.py
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Activation, Dense, Dropout
    from tensorflow.keras.utils import to_categorical
    from tensorflow.keras.optimizers import Adagrad
    from tensorflow.keras.optimizers import Adam
    import numpy as np
    from PIL import Image
    import os
    
    # 学習用のデータを作る.
    image_list = []
    label_list = []
    
    # ./data/train 以下のorange,appleディレクトリ以下の画像を読み込む。
    for dir in os.listdir("data/train"):
        if dir == ".DS_Store":
            continue
    
        dir1 = "data/train/" + dir 
        label = 0
    
        if dir == "apple":    # appleはラベル0
            label = 0
        elif dir == "orange": # orangeはラベル1
            label = 1
    
        for file in os.listdir(dir1):
            if file != ".DS_Store":
                # 配列label_listに正解ラベルを追加(りんご:0 オレンジ:1)
                label_list.append(label)
                filepath = dir1 + "/" + file
                # 画像を25x25pixelに変換し、1要素が[R,G,B]3要素を含む配列の25x25の2次元配列として読み込む。
                # [R,G,B]はそれぞれが0-255の配列。
                image = np.array(Image.open(filepath).resize((25, 25)))
                print(filepath)
                # 配列を変換し、[[Redの配列],[Greenの配列],[Blueの配列]] のような形にする。
                image = image.transpose(2, 0, 1)
                # さらにフラットな1次元配列に変換。最初の1/3はRed、次がGreenの、最後がBlueの要素がフラットに並ぶ。
                image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0]
                # 出来上がった配列をimage_listに追加。
                image_list.append(image / 255.)
    
    # kerasに渡すためにnumpy配列に変換。
    image_list = np.array(image_list)
    
    # ラベルの配列を1と0からなるラベル配列に変更
    # 0 -> [1,0], 1 -> [0,1] という感じ。
    Y = to_categorical(label_list)
    
    # モデルを生成してニューラルネットを構築
    model = Sequential()
    model.add(Dense(200, input_dim=1875))
    model.add(Activation("relu"))
    model.add(Dropout(0.2))
    
    model.add(Dense(200))
    model.add(Activation("relu"))
    model.add(Dropout(0.2))
    
    model.add(Dense(2))
    model.add(Activation("softmax"))
    
    # オプティマイザにAdamを使用
    opt = Adam(lr=0.001)
    # モデルをコンパイル
    model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])
    # 学習を実行。10%はテストに使用。
    model.fit(image_list, Y, epochs=1500, batch_size=100, validation_split=0.1)
    
    # テスト用ディレクトリ(./data/train/)の画像でチェック。正解率を表示する。
    total = 0.
    ok_count = 0.
    
    for dir in os.listdir("data/train"):
        if dir == ".DS_Store":
            continue
    
        dir1 = "data/test/" + dir 
        label = 0
    
        if dir == "apple":
            label = 0
        elif dir == "orange":
            label = 1
    
        for file in os.listdir(dir1):
            if file != ".DS_Store":
                label_list.append(label)
                filepath = dir1 + "/" + file
                image = np.array(Image.open(filepath).resize((25, 25)))
                print(filepath)
                image = image.transpose(2, 0, 1)
                image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0]
                result = model.predict_classes(np.array([image / 255.]))
                print("label:", label, "result:", result[0])
    
                total += 1.
    
                if label == result[0]:
                    ok_count += 1.
    
    print("seikai: ", ok_count / total * 100, "%")
    
    위에서 집행한 결과는 다음과 같다.
    (学習過程の出力)....
    Epoch 1498/1500
    1/1 [==============================] - 0s 12ms/step - loss: 7.6416e-07 - accuracy: 1.0000 - val_loss: 0.6871 - val_accuracy: 0.8000
    Epoch 1499/1500
    1/1 [==============================] - 0s 12ms/step - loss: 6.8343e-06 - accuracy: 1.0000 - val_loss: 0.6892 - val_accuracy: 0.8000
    Epoch 1500/1500
    1/1 [==============================] - 0s 12ms/step - loss: 7.7979e-05 - accuracy: 1.0000 - val_loss: 0.7102 - val_accuracy: 0.8000
    
    상기 스크립트에서 학습이 완료되면 자동으로 판정을 실행합니다.
    수행 결과일 뿐이라면 이해하기 어려우니 실제 판정된 사진을 첨부해 주세요.

    판정 결과



    data/test/apple/huji_mutai1.jpg
    label: 0 result: 0(判定は result:0 = りんご。正解)
    

    data/test/apple/keyvisual02.jpg
    label: 0 result: 0(判定は result:0 = りんご。正解)
    

    data/test/apple/reitou--770x513.jpg
    label: 0 result: 0(判定は result:0 = りんご。正解)
    

    data/test/apple/1609302619_2.jpg
    label: 0 result: 0(判定は result:0 = りんご。正解)
    

    data/test/apple/51qu+EJFNuL._SL500_.jpg
    label: 0 result: 0(判定は result:0 = りんご。正解)
    

    data/test/orange/resized_6800084d-2f12-419b-a2b1-81d7aad38001.jpg
    label: 1 result: 1(判定は result:1 = オレンジ。正解)
    

    data/test/orange/sheraz-shaikh-Zx3kcU2Kw9E-unsplash.jpg
    label: 1 result: 1(判定は result:1 = オレンジ。正解)
    

    data/test/orange/7202_orange3.jpg
    label: 1 result: 1(判定は result:1 = オレンジ。正解)
    

    data/test/orange/wide_thumbnail_normal.jpg
    label: 1 result: 1(判定は result:1 = オレンジ。正解)
    

    정확도


    seikai:  100.0 %(正解率100%)
    
    이번 정확도는 100%이지만 매번 100%가 아닌 90%인 경우도 있다.

    감상


    일단 모르기 때문에 거칠게 1차원 배열로 바꾸어 봐도 그에 상응하는 판별이 가능하다.다만, 이렇게 되면 얼굴 판별이 어려울 것 같다.더 미묘한 차이를 판별하는 방법에 도전하고 싶다.

    좋은 웹페이지 즐겨찾기