rank-1, rank-5rank-N 정확도의 개념에 대해 논의하겠습니다. 특히 컴퓨터 비전 및 이미지 분류 공간에서 딥러닝 문헌을 읽을 때 ranked accuracy라는 개념을 접하게 될 것입니다. 예를 들어 ImageNet 데이터 세트에서 평가된 머신 러닝 방법을 제시하는 거의 모든 논문은 rank-1 및 rank-5 정확도 측면에서 결과를 제시합니다.

 

rank-1 rank-5 정확도는 정확히 무엇인지 그리고 기존의 정확도 (, 정밀도) 어떻게 다른지 알아보겠습니다. ranked accuracyFlowers-17 CALTECH-101 데이터 세트에서 훈련 기계 학습 모델에 적용합니다.

 

Ranked Accuracy

왼쪽 : 신경망이 분류하려고하는 개구리의 입력 이미지. 오른쪽 : 자동차의 입력 이미지.

 

 

ranked accuracy는 다음 예를 통해 설명할 수 있습니다. 비행기, 자동차, 새, 고양이, 사슴, 개, 개구리, 말, 배, 트럭 등 10가지 클래스가 포함 된 CIFAR-10 데이터 세트에서 훈련 된 신경망을 평가한다고 가정 해 보겠습니다. 

 

왼쪽 : 개구리그림에 대해 신경망이 반환 한 클래스 레이블 확률. 오른쪽 : 자동차에 대해 네트워크에서 반환 한 클래스 레이블 확률

입력 이미지(개구리)가 주어지면 신경망에 각 클래스 레이블에 대한 확률을 계산하도록 합니다. 그러면 신경망은 표(왼쪽)에 나열된 클래스 레이블 확률을 반환합니다.

 

입력 이미지 (개구리)가 주어지면 신경망에 각 클래스 레이블에 대한 확률을 계산하도록 요청합니다. 그러면 신경망은 표 (왼쪽)에 나열된 클래스 레이블 확률을 반환합니다.

확률이 가장 큰 클래스 레이블은 실제로 정확한 예측 인 frog(97.3 %)입니다. 이 과정을 반복한다면 :
1단계 : 데이터 세트의 각 입력 이미지에 대한 클래스 레이블 확률 계산합니다.
2단계 : 실측 레이블이 확률이 가장 큰 예측 클래스 레이블과 같은지 결정합니다.
3단계 : 2단계가 참인 횟수를 계산합니다.

우리는 rank-1 정확도에 도달하는 것이 목표입니다. 따라서 rank-1 정확도는 최상위 예측이 실측 레이블과 일치하는 예측의 백분율입니다. 이것이 우리가 계산하는 데 사용되는 "표준"유형의 정확도입니다. 올바른 예측의 총 수를 데이터 포인트 수로 나눕니다.

그런 다음 이 개념을 rank-5 정확도로 확장 할 수 있습니다. 1위 예측에만 신경을 쓰지 않고 상위 5개 예측까지 고려합니다. 그러면 평가 프로세스는 다음과 같습니다.

1 단계 : 데이터 세트의 입력 이미지에 대한 클래스 레이블 확률을 계산합니다.
2단계 : 예측된 클래스 레이블 확률을 내림차순으로 정렬하여 확률이 더 높은 레이블이 목록의 맨 앞에 배치되도록합니다.
3단계 : 2단계의 상위 5개 예측 레이블에 실측 레이블이 있는지 확인합니다.
4단계 : 3단계가 참인 횟수를 계산합니다.

rank-5는 단순히 rank-1 정확도의 확장입니다. 네트워크에서 상위 5 개의 예측을 고려하기 때문입니다. 예를 들어 임의의 신경망을 기반으로 CIFAR-10 범주로 분류 할 입력 이미지를 다시 생각해 보겠습니다 (자동차). 네트워크를 통과 한 후 표(오른쪽)에 자세히 설명 된 클래스 레이블 확률을 얻습니다.

 

우리의 이미지는 분명히 자동차입니다. 그러나 우리 네트워크는 트럭을 최고의 예측으로 판단했습니다.
– 이 것은 rank-1 정확도에 대한 잘못된 예측으로 간주됩니다. 그러나 네트워크의 상위 5개 예측을 살펴보면 자동차가 실제로 2위 예측이라는 것을 알 수 있으며 이는 rank-5를 계산할 때 정확합니다. 이 접근 방식은 임의의 랭크 N 정확도로 쉽게 확장 될 수 있습니다. 그러나 우리는 일반적으로 rank-1 및 rank-5 정확도만 계산합니다. 이는 왜 rank-5 정확도를 계산해야 하는가?에 대한 의문이 생길 수 있습니다.

CIFAR-10 데이터 세트의 경우 rank-5 정확도를 계산하는 것은 약간 어리석은 일이지만 크고 까다로운 데이터 세트, 특히 세분화 된 분류의 경우 특정 CNN에서 rank-5개 예측을 보는 것이 도움이 되는 경우가 많습니다. 아마도 우리가 rank-1 및 rank-5 정확도를 계산하는 이유에 대한 가장 좋은 예는 Szegedy et al. 왼쪽에는 시베리안 허스키, 오른쪽에는 에스키모 개가 있습니다. 대부분의 인간은 두 동물의 차이를 인식하지 못할 것입니다. 그러나이 두 클래스는 ImageNet 데이터 세트에서 유효한 레이블입니다.

왼쪽 : 시베리안 허스키. 오른쪽 : 에스키모 개.

유사한 특성을 가진 많은 클래스 레이블을 포함하는 대규모 데이터 세트로 작업 할 때 네트워크 성능을 확인하기 위해 rank-1 정확도의 확장으로 rank-5 정확도를 종종 검사합니다. 이상적인 세계에서 rank-1 정확도는 rank-5 정확도와 동일한 비율로 증가하지만 까다롭거나 실제 데이터 세트에서는 항상 그런 것은 아닙니다.

따라서 학습이 진행중에도 여전히 "학습"중인지 확인하기 위해 rank-5 정확도도 조사합니다. rank-1 정확도가 훈련이 끝날 무렵 정체되는 경우 일 수 있지만, 우리가 만든 네트워크가 더 많은 차별적 기능을 학습함에 따라 rank-5 정확도는 계속 향상됩니다 (그러나 rank-1 예측을 추월 할만큼 차별적이지는 않음). 

사전 훈련 된 CNN을 사용하여 소수의 데이터 세트에서 특성을 추출 했으므로 특히 VGG16Animals, CALTECH-101 또는 _Flowers-17_이 아닌 ImageNet에서 훈련되었다는 점을 고려할 때 이러한 특성이 실제로 얼마나 발휘되는지 확인해보겠습니다.

간단한 선형 모델이 이러한 특징을 사용하여 이미지를 분류할 때 얼마나 그 효과는 얼마나 될까요?
새 파일을 열고 이름을 train_model.py로 지정하고 다음 코드를 작성합니다.

# USAGE
# python train_model.py --db ../datasets/animals/hdf5/features.hdf5 \
#    --model animals.cpickle
# python train_model.py --db ../datasets/caltech-101/hdf5/features.hdf5 \
#    --model caltech101.cpickle
# python train_model.py --db ../datasets/flowers17/hdf5/features.hdf5 \
#    --model flowers17.cpickle

# import the necessary packages
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
import argparse
import pickle
import h5py

GridSearchCV클래스는 매개 변수를 LogisticRegression 분류기로 바꾸는 데 사용됩니다. 학습 후에는 pickle을 사용하여 LogisticRegression 모델을 디스크에 직렬화합니다.

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--db", required=True,
    help="path HDF5 database")
ap.add_argument("-m", "--model", required=True,
    help="path to output model")
ap.add_argument("-j", "--jobs", type=int, default=-1,
    help="# of jobs to run when tuning hyperparameters")
args = vars(ap.parse_args())

스크립트에는 두 개의 명령 줄 인수와 세 번째 선택적 인수가 필요합니다.

  1. --db : 추출된 기능 및 클래스 레이블이 포함 된 HDF5 데이터 세트의 경로입니다.
  2. --model : 여기서 출력 로지스틱 회귀 분류기에 대한 경로를 제공합니다.
  3. --jobs : 하이퍼 파라미터를 로지스틱 회귀 모델에 맞게 조정하기 위해 그리드 검색을 실행할 때 동시 작업 수를 지정하는 데 사용되는 선택적 정수입니다.

HDF5 데이터 세트를 열고 학습/테스트 분할 위치를 결정하겠습니다.

# open the HDF5 database for reading then determine the index of
# the training and testing split, provided that this data was
# already shuffled *prior* to writing it to disk
db = h5py.File(args["db"], "r")
i = int(db["labels"].shape[0] * 0.75)

이 장의 앞부분에서 언급했듯이, 우리는 관련 이미지 / 특징 벡터를 HDF5 데이터 세트에 쓰기 전에 의도적으로 이미지 경로를 셔플했습니다.이 이유는 라인 22와 23에서 명확 해집니다.

데이터 세트가 너무 커서 메모리에 넣을 수 없기 때문에 훈련 및 테스트 분할을 결정하는 효율적인 방법이 필요합니다. HDF5 데이터 세트에 얼마나 많은 항목이 있는지 알고 있기 때문에 (그리고 데이터의 75 %를 훈련에 사용하고 25 %를 평가에 사용하고자 함을 알고 있으므로) 데이터베이스에 75 % 인덱스 i를 간단히 계산할 수 있습니다. 인덱스 i 이전의 모든 데이터는 훈련 데이터로 간주됩니다. i 이후의 모든 데이터는 데이터를 테스트합니다.

훈련 및 테스트 분할을 고려하여 로지스틱 회귀 분류기를 훈련 해 보겠습니다.

# define the set of parameters that we want to tune then start a
# grid search where we evaluate our model for each value of C
print("[INFO] tuning hyperparameters...")
params = {"C": [0.1, 1.0, 10.0, 100.0, 1000.0, 10000.0]}
model = GridSearchCV(LogisticRegression(solver="lbfgs",
    multi_class="auto"), params, cv=3, n_jobs=args["jobs"])
model.fit(db["features"][:i], db["labels"][:i])
print("[INFO] best hyperparameters: {}".format(model.best_params_))

# evaluate the model
print("[INFO] evaluating...")
preds = model.predict(db["features"][i:])
print(classification_report(db["labels"][i:], preds,
    target_names=db["label_names"]))

28-31 행은 최적 값이 무엇인지 결정하기 위해 로지스틱 회귀 분류기의 엄격함 인 매개 변수 C에 대한 그리드 검색을 실행합니다. Logistic Regression에 대한 자세한 검토는이 책의 범위를 벗어나므로 Logistic Regression 분류기 [13]에 대한 철저한 검토는 Andrew Ng의 메모를 참조하십시오.

배열 슬라이스를 통해 훈련 데이터와 훈련 레이블을 어떻게 표시하는지 확인하십시오.

# evaluate the model
print("[INFO] evaluating...")
preds = model.predict(db["features"][i:])
print(classification_report(db["labels"][i:], preds,
    target_names=db["label_names"]))

다시 말하지만, 인덱스 i 이전의 모든 데이터는 훈련 세트의 일부입니다. 최상의 하이퍼 파라미터가 발견되면 테스트 데이터에서 분류자를 평가합니다 (36-38 행).

여기에서 테스트 데이터와 테스트 레이블은 배열 슬라이스를 통해 액세스됩니다.

인덱스 i 이후의 모든 것은 테스트 세트의 일부입니다. HDF5 데이터 세트가 디스크에 있고 (메모리에 맞추기에는 너무 커서) NumPy 배열 인 것처럼 처리 할 수 있습니다. 이는 HDF5 및 h5py를 딥 러닝 및 머신에 함께 사용하는 것의 큰 장점 중 하나입니다. 학습 과제.

마지막으로 LogisticRegression 모델을 디스크에 저장하고 데이터베이스를 닫습니다.

# serialize the model to disk
print("[INFO] saving model...")
f = open(args["model"], "wb")
f.write(pickle.dumps(model.best_estimator_))
f.close()

# close the database
db.close()

 

'keras > 2. Feature Extractors' 카테고리의 다른 글

3. The Feature Extraction Process  (0) 2020.08.24
2. Writing Features to an HDF5 Dataset  (0) 2020.08.22
1. Networks as Feature Extractors  (0) 2020.08.22

임의의 이미지 데이터세트에서 특징을 추출하는데 사용할수있는 Python스크립트를 정의해보겠습니다(입력데이터세트가 특정디렉토리구조를 따르는경우). 새파일을 열고 이름을 extract_features.py로지정하여 작업을 시작하겠습니다.

 

사전 훈련 된 VGG16 네트워크의 Keras 구현을 가져와 기능 추출기로 사용하겠습니다. LabelEncoder() 클래스는 클래스 레이블을 문자열에서 정수로 변환하는 데 사용됩니다. 또한 7 행에서 HDF5DatasetWriter를 가져 와서 CNN에서 추출한 기능을 HDF5 데이터 세트에 쓸 수 있습니다.

 

tqdm 모듈을 이용하여 진행 표시줄을 추가하겠습니다.

# USAGE
# python extract_features.py --dataset datasets/animals/images \
#     --output datasets/animals/hdf5/features.hdf5
# python extract_features.py --dataset datasets/caltech-101/images \
#     --output datasets/caltech-101/hdf5/features.hdf5
# python extract_features.py --dataset datasets/flowers17/images \
#     --output datasets/flowers17/hdf5/features.hdf5

# import the necessary packages
from keras.applications import VGG16
from keras.applications import imagenet_utils
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import load_img
from sklearn.preprocessing import LabelEncoder
from inout.hdf5datasetwriter import HDF5DatasetWriter
from imutils import paths
from tqdm import tqdm
import numpy as np
import argparse
import random
import os

extract_features.py 스크립트에는 두 개의 명령 줄 인수와 두 개의 선택적 인수가 필요합니다. --dataset argument는 기능을 추출하려는 이미지의 입력 디렉토리 경로를 제어합니다. --output argument는 출력 HDF5 데이터 파일의 경로를 결정합니다.

 

그런 다음 --batch-size를 제공할 수 있습니다. 이것은 한 번에 VGG16을 통해 전달되는 배치의 이미지 수입니다. 여기에서는 32의 값이 합리적이지만 시스템에 충분한 메모리가 있으면 값을 늘릴 수 있습니다. --buffer-size 스위치는 HDF5 데이터 세트용 버퍼를 쓰기 전에 메모리에 저장할 추출 된 특징의 수를 제어합니다. 다시 말하지만, 컴퓨터에 충분한 메모리가 있으면 버퍼 크기를 늘릴 수 있습니다.

 

다음 단계는 디스크에서 이미지 경로를 가져 와서 정리하고 레이블을 인코딩하는 것입니다.

# store the batch size in a convenience variable
bs = args["batch_size"]

# grab the list of images that we'll be describing then randomly
# shuffle them to allow for easy training and testing splits via
# array slicing during training time
print("[INFO] loading images...")
imagePaths = list(paths.list_images(args["dataset"]))
random.shuffle(imagePaths)

# extract the class labels from the image paths then encode the
# labels
labels = [p.split(os.path.sep)[-2] for p in imagePaths]
le = LabelEncoder()
labels = le.fit_transform(labels)

데이터 세트의 모든 이미지에 대한 파일인 imagePaths를 가져옵니다. 그런 다음 이 데이터셋을 셔플합니다. 파일 경로가 디렉토리 구조를 갖는다 고 가정하고 파일 경로에서 클래스 레이블 이름을 추출합니다.

# load the VGG16 network
print("[INFO] loading network...")
model = VGG16(weights="imagenet", include_top=False)

# initialize the HDF5 dataset writer, then store the class label
# names in the dataset
dataset = HDF5DatasetWriter(
    (len(imagePaths), 512 * 7 * 7),
    args["output"],
    dataKey="features",
    bufSize=args["buffer_size"],
)
dataset.storeClassLabels(le.classes_)

우리의 데이터 셋이 이 디렉토리 구조를 따르는 경우, 구분 기호 (Unix 컴퓨터에서는 '/', Windows에서는 '')를 기반으로 경로를 배열로 분할 한 다음 배열의 마지막에서 두 번째 항목(이 작업은 특정 이미지의 클래스 레이블을 생성)합니다. 레이블이 주어지면 정수로 인코딩합니다 (학습 프로세스 중에 원-핫 인코딩을 수행합니다).

 

이제 VGG16 네트워크 가중치를 로드하고 HDF5DatasetWriter를 인스턴스화 할 수 있습니다.

 

디스크에서 사전 훈련된 VGG16 네트워크를 로드합니다. 그러나 include_top = False 매개 변수는 최종 완전 연결 계층이 아키텍처에 포함되지 않아야 함을 나타냅니다. 따라서 네트워크를 통해 이미지를 순방향 전파 할 때 FC 계층의 소프트 맥스 분류기에 의해 생성된 확률보다는 최종 POOL 계층 이후의 특성 값을 얻습니다.

 

HDF5DatasetWriter를 인스턴스화합니다. 첫 번째 매개 변수는 데이터 세트의 차원으로, 각각 512x7x7 = 25,088크기의 특징 벡터를 갖는 총 이미지 len(imagePaths)이 있습니다. 그런 다음 레이블 인코더에 따라 클래스 레이블의 문자열 이름을 저장합니다.

이제 실제 특징 추출을 시작하겠습니다.

image_iter = np.arange(0, len(imagePaths), bs)
# loop over the images in batches
for i in tqdm(
    image_iter, total=len(image_iter), desc="Extracting Features"
):
    # extract the batch of images and labels, then initialize the
    # list of actual images that will be passed through the network
    # for feature extraction
    batchPaths = imagePaths[i : i + bs]
    batchLabels = labels[i : i + bs]
    batchImages = []

--batch-size 배치로 imagePaths를 반복하기 시작합니다. 해당 배치에 대한 이미지 경로와 레이블을 추출하고, VGG16에로드 및 공급 될 이미지를 저장하는 목록을 초기화합니다.

특징 추출을 위해 이미지를 준비하는 것은 CNN을 통해 분류 할 이미지를 준비하는 것과 정확히 동일합니다.

    for (j, imagePath) in enumerate(batchPaths):
        # load the input image using the Keras helper utility
        # while ensuring the image is resized to 224x224 pixels
        image = load_img(imagePath, target_size=(224, 224))
        image = img_to_array(image)

        # preprocess the image by (1) expanding the dimensions and
        # (2) subtracting the mean RGB pixel intensity from the
        # ImageNet dataset
        image = np.expand_dims(image, axis=0)
        image = imagenet_utils.preprocess_input(image)

        # add the image to the batch
        batchImages.append(image)

배치의 각 이미지 경로를 반복합니다. 각 이미지는 디스크에서 로드되고 Keras 호환 어레이로 변환됩니다. 그런 다음 이미지를 전처리 한 다음 batchImages에 추가합니다.

 

batchImages의 이미지에 대한 특징 벡터를 얻으려면 모델의 .predict 메서드를 호출하기 만하면됩니다.

    # pass the images through the network and use the outputs as
    # our actual features
    batchImages = np.vstack(batchImages)
    features = model.predict(batchImages, batch_size=bs)

    # reshape the features so that each image is represented by
    # a flattened feature vector of the `MaxPooling2D` outputs
    features = features.reshape((features.shape[0], 512 * 7 * 7))

    # add the features and labels to our HDF5 dataset
    dataset.add(features, batchLabels)


# close the dataset
dataset.close()

NumPy.vstack 방법을 사용하여 이미지가 모양 (N, 224, 224, 3)을 갖도록 이미지를 "수직으로 스택"합니다. 여기서 N은 배치의 크기입니다.

 

네트워크를 통해 batchImages를 전달하면 실제 특성 벡터가 생성됩니다. VGG16의 헤드에서 완전히 연결된 레이어를 잘라 냈으므로 이제 최종 최대 풀링 작업 후에 값이 남습니다. 그러나 POOL의 출력은 모양 (N, 512, 7, 7)을 가지며, 이는 각각 크기가 7 x 7512개의 필터가 있음을 의미합니다. 이러한 값을 특성 벡터로 취급하려면, 모양 (N, 25088)을 가진 배열로 변환해야합니다. HDF5 데이터 세트에 기능과 batchLabels를 추가합니다.

 

최종 코드 블록은 HDF5 데이터 세트 닫기를 처리합니다.

python extract_features.py --dataset ~/data/animals/images/ \
--output datasets/animals/hdfs/features.hdf5

python extract_features.py --dataset ~/data/caltech-101/images/ \
--output datasets/caltech-101/hdfs/features.hdf5

python extract_features.py --dataset ~/data/flowers17/images/ \
--output datasets/flowers17/hdfs/features.hdf5

이작업은 cpu환경에서는 매우 오래 걸리므로 gpu환경에서 하는 것을 추천합니다.

 

feature extractor가 진행되는 과정

feature_extractors.tar.gz
0.18MB

 

VGG16 (또는 다른 CNN)을 기능 추출기로 만들기 전에 먼저 약간의 인프라를 개발해야합니다. 특히, 이름에서 알 수 있듯이 NumPy 배열 (기능, 원시 이미지 등)의 입력 세트를 가져와 HDF5 형식으로 작성하는 역할을하는 HDF5DatasetWriter라는 Python 클래스를 정의해야합니다.

이 클래스 내에서 기능을 빌드하려면 두 개의 Python 패키지 만 필요합니다. 내장된 os 모듈과 h5py이므로 HDF5 바인딩에 액세스 할 수 있습니다.

거기에서 생성자를 정의하겠습니다.

# import the necessary packages
import h5py
import os


class HDF5DatasetWriter:
    def __init__(self, dims, outputPath, dataKey="images", bufSize=1000):
        # check to see if the output path exists, and if so, raise
        # an exception
        if os.path.exists(outputPath):
            raise ValueError(
                "The supplied `outputPath` already "
                "exists and cannot be overwritten. Manually delete "
                "the file before continuing.",
                outputPath,
            )

        # open the HDF5 database for writing and create two datasets:
        # one to store the images/features and another to store the
        # class labels
        self.db = h5py.File(outputPath, "w")
        self.data = self.db.create_dataset(dataKey, dims, dtype="float")
        self.labels = self.db.create_dataset("labels", (dims[0],), dtype="int")

        # store the buffer size, then initialize the buffer itself
        # along with the index into the datasets
        self.bufSize = bufSize
        self.buffer = {"data": [], "labels": []}
        self.idx = 0

HDF5DatasetWriter의 생성자는 4개의 매개 변수를 허용하며 그 중 2개는 선택 사항입니다. dims 매개 변수는 데이터 세트에 저장할 데이터의 크기 또는 모양을 제어합니다. dimsNumPy.shape라고 생각할 수 있습니다. 28 × 28 = 784 MNIST 데이터 세트의 (플래 팅 된) 원시 픽셀 강도를 저장하는 경우 MNIST에 각각 784의 차원을 가진 70,000 개의 예제가 있으므로 dims = (70000, 784) 입니다. CIFAR-10 이미지의 경우 CIFAR-10 데이터 세트에 총 60,000 개의 이미지가 있으며 각 이미지는 32x32x3 RGB 이미지로 표시되므로 dims = (60000, 32, 32, 3)입니다.

 

전이 학습 및 특징 추출의 맥락에서 VGG16 아키텍처를 사용하고 최종 POOL 계층 이후에 출력을 가져옵니다. 최종 POOL 레이어의 출력은 512x 7 x 7이며, 이 차원을 펼치면 길이가 25,088 인 특징 벡터를 생성합니다. 따라서 특징 추출에 VGG16을 사용하는 경우 dims = (N, 25088)을 설정합니다. 여기서 N은 데이터 세트의 총 이미지 수입니다.

 

HDF5DatasetWriter 생성자의 다음 매개 변수는 outputPath입니다. 이것은 출력 HDF5 파일이 디스크에 저장 될 경로입니다. 선택적 dataKey는 알고리즘이 학습 할 데이터를 저장할 데이터 세트의 이름입니다. 대부분의 경우 원시 이미지를 HDF5 형식으로 저장하므로이 값의 기본값은 "image"입니다. CNN에서 추출한 기능을 파일에 저장하고 있음을 나타 내기 위해 dataKey = "features"를 설정합니다.

마지막으로 bufSize는 인 메모리 버퍼의 크기를 제어하며 기본적으로 1,000 개의 특징 벡터 / 이미지로 설정됩니다. bufSize에 도달하면 버퍼를 HDF5 데이터 세트로 넘깁니다.

그런 다음 outputPath가 이미 존재하는지 확인합니다. 이 경우 기존 데이터베이스를 덮어 쓰지 않기 때문에 최종 사용자에게 오류가 발생합니다.


제공된 outputPath를 사용하여 쓰기위한 HDF5 파일을 엽니다. dataKey 이름과 제공된 값을 사용하여 데이터 세트를 만듭니다. 여기에 원시 이미지 / 추출 된 기능이 저장됩니다. 두 번째 데이터 세트를 생성합니다. 이 데이터 세트는 데이터 세트의 각 레코드에 대한 (정수) 클래스 레이블을 저장한 다음 버퍼를 초기화합니다.

다음으로 버퍼에 데이터를 추가하는 데 사용되는 add 메서드입니다.

    def add(self, rows, labels):
        # add the rows and labels to the buffer
        self.buffer["data"].extend(rows)
        self.buffer["labels"].extend(labels)

        # check to see if the buffer needs to be flushed to disk
        if len(self.buffer["data"]) >= self.bufSize:
            self.flush()

add 메서드에는 두 개의 매개 변수가 필요합니다. 데이터 세트에 추가 할 과 해당하는 클래스 라벨입니다. 행과 레이블은 모두 각 버퍼에 추가됩니다. 버퍼가 가득 차면 flush 메소드를 호출하여 파일을 작성하고 재설정합니다.

플러시 방법에 대해 이제 함수를 정의하겠습니다.

 

    def flush(self):
        # write the buffers to disk then reset the buffer
        i = self.idx + len(self.buffer["data"])
        self.data[self.idx : i] = self.buffer["data"]
        self.labels[self.idx : i] = self.buffer["labels"]
        self.idx = i
        self.buffer = {"data": [], "labels": []}

 

또한 storeClassLabels라는 편리한 유틸리티 함수를 정의합니다.이 함수가 호출되면 별도의 데이터 세트에 클래스 레이블의 원래 문자열 이름을 저장합니다.

    def storeClassLabels(self, classLabels):
        # create a dataset to store the actual class label names,
        # then store the class labels
        dt = h5py.special_dtype(vlen=str)  # `vlen=unicode` for Py2.7
        labelSet = self.db.create_dataset("label_names", (len(classLabels),), dtype=dt)
        labelSet[:] = classLabels

 

마지막으로 마지막 함수 close는 버퍼에 남아있는 데이터를 HDF5에 쓰고 데이터 세트를 닫는데 사용됩니다.

    def close(self):
        # check to see if there are any other entries in the buffer
        # that need to be flushed to disk
        if len(self.buffer["data"]) > 0:
            self.flush()

        # close the dataset
        self.db.close()

HDF5DatasetWriter는 머신 러닝이나 딥러닝과 전혀 관련이 없습니다. 단순히 데이터를 HDF5 형식으로 저장하는 데 사용되는 클래스일 뿐입니다. 딥러닝을 계속하면서 새로운 문제를 설정할 때 초기 작업의 대부분은 작업할 수 있는 형식으로 데이터를 가져 오는 것임을 알게 될 것입니다. 조작하기 쉬운 형식의 데이터가 있으면 머신러닝 및 딥러닝 기술을 데이터에 적용하기가 훨씬 쉬워집니다.

즉, HDF5DatasetWriter 클래스는 딥 러닝 및 컴퓨터 비전에 특화되지 않은 유틸리티 클래스입니다.


hdf5datasetwriter.py
0.00MB

 

이제 전이 학습의 개념, 사전 학습 된 모델을 'shortcut'으로 사용하여 원래 학습되지 않은 데이터에서 패턴을 학습하는 기능을 알아보겠습니다.

 

Transfer learning(전이 학습)은 다른 훈련 패러다임을 제안합니다. 기존의 사전 훈련된 분류기를 사용할 수 있고 이를 새로운 분류 작업의 시작점으로 사용할 수 있다면 탁월한 성능을 발휘할 것 같습니다.

 

ImageNet 같은 대규모 데이터 세트에서 훈련된 심층 신경망은 전이 학습 작업에서 탁월함을 입증했습니다. 이러한 네트워크는 1,000 개의 개별 객체 클래스를 인식하기 위해 풍부하고 차별화된 기능 세트를 학습합니다. 이러한 필터는 CNN 원래 훈련된 이외의 분류 작업에 재사용 있습니다.

 

일반적으로 컴퓨터 비전을위한 딥 러닝에 적용될 때 두 가지 유형의 전이 학습이 있습니다.
1. 네트워크를 임의의 기능 추출기로 취급합니다.
2. 기존 네트워크의 완전히 연결된 계층을 제거하고 CNN 위에 새 Fully Connected 계층 세트를 배치하고 이러한 가중치 (및 선택적으로 이전 계층)를 미세 조정하여 객체 클래스를 인식합니다.

이 장에서는 네트워크를 특징 추출기로 취급하는 첫 번째 전이 학습 방법에 주로 초점을 맞출 것입니다. 그런 다음 5 장에서 특정 분류 작업에 대한 네트워크의 가중치를 미세 조정하는 방법에 대해 설명합니다.

Extracting Features with a Pre-trained CNN

지금까지 우리는 Convolutional Neural Networks를 이미지 분류기로 취급했습니다.
1. 네트워크에 이미지를 입력합니다.
2. 이미지가 네트워크를 통해 전달됩니다.
3. 우리는 네트워크 끝에서 최종 분류 확률을 얻습니다.

그러나 이미지가 전체 네트워크를 통해 전파되도록 해야한다는 "규칙"은 없습니다. 대신 활성화 또는 풀링 레이어와 같은 임의의 레이어에서 전파를 중지하고 이때 네트워크에서 값을 추출한 다음 이를 특징 벡터로 사용할 수 있습니다. 예를 들어 Simonyan과 Zisserman의 VGG16 네트워크 아키텍처를 살펴 보겠습니다.

왼쪽 : 1,000 개의 ImageNet 클래스 레이블 각각에 대한 확률을 출력하는 원래 VGG16 네트워크 아키텍처. 오른쪽 : VGG16에서 FC 레이어를 제거하고 대신 최종 POOL 레이어의 출력을 반환합니다. 이 출력은 추출 된 기능으로 사용됩니다.

 

네트워크의 레이어와 함께 각 레이어에 대한 볼륨의 입력 및 출력 모양도 포함했습니다. 네트워크를 특징 추출기로 취급 할 때, 우리는 본질적으로 임의의 지점 (일반적으로 완전히 연결된 계층 이전에 있지만 실제로는 특정 데이터 세트에 따라 다름)에서 네트워크를 "잘라냅니다".

 

이제 우리 네트워크의 마지막 계층은 최대 풀링 계층 (그림의 오른쪽)으로, 7x7x512의 출력 모양을 가지므로 각각 크기가 7x7 인 512 개의 필터가 있음을 의미합니다. FC 헤드가 제거 된 상태에서이 네트워크를 통해 이미지를 전달하려면 이미지 콘텐츠를 기반으로 활성화되거나 활성화되지 않은 512, 7x7 활성화가 남게됩니다. 따라서 실제로이 7x7x512 = 25,088 값을 가져 와서 이미지의 내용을 정량화하는 특징 벡터로 취급 할 수 있습니다.

전체 이미지 데이터 세트 (VGG16이 학습되지 않은 데이터 세트 포함)에 대해이 프로세스를 반복하면 N 개의 이미지로 구성된 디자인 매트릭스가 남게됩니다. 각 이미지에는 콘텐츠를 정량화하는 데 사용되는 25,088 개의 열이 있습니다 (예 : 특징 벡터) . 특징 벡터가 주어지면 선형 SVM, 로지스틱 회귀 분류기 또는 랜덤 포레스트와 같은 기성 기계 학습 모델을 이러한 기능 위에 훈련시켜 새로운 이미지 클래스를 인식하는 분류기를 얻을 수 있습니다.

CNN 자체는 이러한 새로운 클래스를 인식 할 수 없습니다. 대신 CNN을 중간 기능 추출기로 사용하고 있습니다. 다운 스트림 머신 러닝 분류기는 CNN에서 추출 된 기능의 기본 패턴을 학습합니다.

사전 훈련 된 CNN (특히 VGG16) 및 Keras 라이브러리를 사용하여 Animals, CALTECH-101 및 Flowers-17과 같은 이미지 데이터 세트에서 95 % 이상의 분류 정확도를 얻을 수 있습니다. 이러한 데이터 세트에는 VGG16이 훈련 된 이미지가 포함되어 있지 않지만 전이 학습을 적용하여 적은 노력으로 매우 정확한 이미지 분류기를 구축 할 수 있습니다. 비결은 이러한 기능을 추출하여 효율적인 방식으로 저장하는 것입니다. 이 작업을 수행하려면 HDF5가 필요합니다.

 

What Is HDF5?

HDF5는 HDF5 그룹에서 만든 이진 데이터 형식으로, 데이터 집합 행에 대한 쉬운 액세스 및 계산을 용이하게하면서 디스크에 거대한 숫자 데이터 집합 (메모리에 저장하기에 너무 큼)을 저장합니다. HDF5의 데이터는 파일 시스템이 데이터를 저장하는 방식과 유사하게 계층 적으로 저장됩니다. 데이터는 먼저 그룹으로 정의되며, 그룹은 데이터 세트 및 기타 그룹을 보유 할 수있는 컨테이너와 같은 구조입니다. 그룹이 정의되면 그룹 내에서 데이터 세트를 만들 수 있습니다. 데이터 세트는 동종 데이터 유형 (정수, 플로트, 유니 코드 등)의 다차원 배열 (즉, NumPy 배열)로 생각할 수 있습니다. 

 

HDF5는 C언어로 작성되었습니다. 그러나 h5py 모듈 (h5py.org)을 사용하면 Python 프로그래밍 언어를 사용하여 기본 C API에 액세스 할 수 있습니다. h5py를 매우 멋지게 만드는 것은 데이터와의 상호 작용이 쉽다는 것입니다. HDF5 데이터 세트에 엄청난 양의 데이터를 저장하고 NumPy와 같은 방식으로 데이터를 조작 할 수 있습니다. 예를 들어 표준 Python 구문을 사용하여 메모리에 로드 된 단순한 NumPy 배열 인 것처럼 디스크에 저장된 멀티 테라 바이트 데이터 세트의 행에 액세스하고 분할 할 수 있습니다. 특수 데이터 구조 덕분에 이러한 슬라이스 및 행 액세스가 빠릅니다. h5py와 함께 HDF5를 사용하는 경우 데이터를 주 메모리에 맞추기에는 너무 크지만 여전히 똑같이 액세스하고 조작할 수 있는 거대한 NumPy 배열로 생각할 수 있습니다.

 

무엇보다도 HDF5 형식이 표준화되어 HDF5 형식으로 저장된 데이터 세트는 본질적으로 이식 가능하며 C, MATLAB 및 Java와 같은 다른 프로그래밍 언어를 사용하는 다른 개발자가 액세스 할 수 있습니다.

 

입력 데이터를 효율적으로 받아들이고 HDF5 데이터 세트에 쓸 수 있는 사용자 지정 Python 클래스를 작성합니다. 이 클래스는 두 가지 용도로 사용됩니다.

 

1. VGG16에서 추출한 기능을 효율적으로 HDF5 데이터 세트에 작성하여 전이 학습을 적용하는 방법을 촉진합니다.

2. 빠른 훈련을 용이하게하기 위해 원래 이미지에서 HDF5  데이터 세트를 생성 있습니다.

 

3개의 데이터 세트가있는 HDF5 파일의 예. 첫 번째 데이터 세트에는 CALTECH-101의 label_names가 포함되어 있습니다. 그런 다음 각 이미지를 해당 클래스 레이블에 매핑하는 레이블이 있습니다. 마지막으로 특징 데이터 세트에는 CNN에서 추출한 이미지 정량화가 포함됩니다.

 

Data Augmentation 적용해보겠습니다. Data Augmentation 어떻게 Overfitting 방지하면서 분류 정확도를 높일 있는지 확인해보겠습니다.  새 파일을 열고 이름을 minivggnet_flowers17_data_aug.py 지정한 다음 작업을 시작해 보겠습니다.

 

필요한 라이브러리를 로드합니다.

from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from libs.nn.conv.minivggnet import MiniVGGNet
from preprocessing.aspectawarepreprocessor import AspectAwarePreprocessor
from preprocessing.imagetoarraypreprocessor import ImageToArrayPreprocessor
from preprocessing.simpledatasetloader import SimpleDatasetLoader
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import SGD
import matplotlib.pyplot as plt
import argparse
from imutils import paths
import numpy as np
import os

 

필요한 argument를 세팅합니다.

다음으로 명령 인수를 기준으로 이미지 경로에서 클래스 이름을 추출해 보겠습니다.

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True, help="path to input dataset")
args = vars(ap.parse_args())

# grab the list of images that we'll be describing, then extract
# the class label names from the image paths
print("[INFO] loading images...")
imagePaths = list(paths.list_images(args["dataset"]))
classNames = [pt.split(os.path.sep)[-2] for pt in imagePaths]
classNames = [str(x) for x in np.unique(classNames)]

 

디스크에서 데이터 세트를로드하고, 훈련 / 테스트 분할을 구성하고, 레이블을 인코딩합니다.

# initialize the image preprocessors
aap = AspectAwarePreprocessor(64, 64)
iap = ImageToArrayPreprocessor()

# load the dataset from disk then scale the raw pixel intensities
# to the range [0, 1]
sdl = SimpleDatasetLoader(preprocessors=[aap, iap])
(data, labels) = sdl.load(imagePaths, verbose=500)
data = data.astype("float") / 255.0

# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
(trainX, testX, trainY, testY) = train_test_split(
    data, labels, test_size=0.25, random_state=42
)

# convert the labels from integers to vectors
trainY = LabelBinarizer().fit_transform(trainY)
testY = LabelBinarizer().fit_transform(testY)

 

다음 코드 블록은 ImageDataGenerator 초기화하므로 매우 중요합니다.

aug = ImageDataGenerator(
    rotation_range=30,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode="nearest",
)

 

여기에서 이미지는 다음과 같습니다.

 

1. 무작위로 ± 30도 회전

2. 0.1의 비율로 수평 및 수직 이동

3. 0.2만큼 전단

4. [0.8, 1.2] 범위에서 균일하게 샘플링하여 확대

5. 무작위로 수평으로 플리핑 정확한 데이터 세트에 따라 이러한 데이터 증가 값을 조정하고 싶을 것입니다.

응용 프로그램에 따라 [10,30] 사이의 회전 범위를 보는 것이 일반적입니다. 수평 및 수직 이동은 일반적으로 [0.1, 0.2] 범위에 속합니다 (확대 / 축소 값도 동일). 이미지를 수평으로 훑어 보는 것이 클래스 레이블을 변경하지 않는 한, 항상 수평 훑어보기도 포함해야합니다.

 

# initialize the optimizer and model
print("[INFO] compiling model...")
opt = SGD(lr=0.05)
model = MiniVGGNet.build(width=64, height=64, depth=3, classes=len(classNames))
model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])

 

그러나 네트워크를 훈련시키는 사용되는 코드는 현재 이미지 생성기를 사용하고 있으므로 약간 변경해야합니다.

# train the network
print("[INFO] training network...")
H = model.fit(
    aug.flow(trainX, trainY, batch_size=32),
    validation_data=(testX, testY),
    steps_per_epoch=len(trainX) // 32,
    epochs=100,
    verbose=1,
)

모델의 .fit 메서드를 호출하는 합니다. 이제 첫 번째 매개 변수는 학습 데이터에서 새로운 학습 샘플을 생성하는 데 사용되는 데이터 증가 함수 인 aug.flow입니다. aug.flow에서는 학습 데이터와 해당 레이블을 전달해야합니다. 또한 생성기가 네트워크를 훈련 할 때 적절한 배치를 구성 할 수 있도록 배치 크기를 제공해야합니다.

 

그런 다음 validation_data를 (testX, testY)의 튜플로 제공합니다.이 데이터는 모든 generation이 끝날 때까지 유효성 검사에 사용됩니다. steps_per_epoch 매개 변수는 epoch 당 배치 수를 제어합니다. 총 훈련 샘플 수를 배치 크기로 나누고 정수로 변환하여 적절한 steps_per_epoch 값을 프로그래밍 방식으로 결정할 수 있습니다. 마지막으로 epochs는 네트워크가 훈련되어야하는 총 epoch 수를 제어합니다 (이 경우 100 epoch).

 

네트워크를 훈련 평가하고 해당 정확도 / 손실 플롯을 플로팅합니다.

# evaluate the network
print("[INFO] evaluating network...")
predictions = model.predict(testX, batch_size=32)
print(
    classification_report(
        testY.argmax(axis=1), predictions.argmax(axis=1), target_names=classNames
    )
)

# plot the training loss and accuracy
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, 100), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, 100), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, 100), H.history["accuracy"], label="train_acc")
plt.plot(np.arange(0, 100), H.history["val_accuracy"], label="val_acc")
plt.title("Training Loss and Accuracy")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.show()

 

위코드는 아래 명령어로 실행시킬 수 있습니다.

 python minivggnet_flowers17_data_aug.py --dataset dataset/flowers17/images/

 

Data Augmentation을 통한 Flower-17 학습과정 및 loss&accuracy plot

Data Augmentation는 훈련 데이터에서 사용하는 정규화 기술의 한 유형입니다. 이름에서 알 수 있듯이 Data Augmentation은 일련의 무작위 변환, 회전, 전단 등을 적용하여 훈련 데이터를 무작위로 생성합니다. 이러한 단순 변환을 적용해도 입력 이미지의 클래스 레이블은 변경되지 않습니다. 그러나 각 증강 이미지는 학습 알고리즘이 이전에 보지 못한 "새로운"이미지로 간주 될 수 있습니다. 따라서 우리의 훈련 알고리즘은 새로운 훈련 샘플과 함께 지속적으로 제공되어 더 강력하고 차별적인 패턴을 학습 할 수 있습니다.

 

"자연스러운"교육 샘플을 수집하는 것이 항상 더 좋지만, 데이터 확대는 작은 데이터 세트 제한을 극복하는 데 사용할 수 있습니다. 자체 훈련의 경우 실행하는 거의 모든 실험에 데이터 증가를 적용해야합니다. CPU가 이제 입력을 무작위로 변환하는 책임이 있기 때문에 약간의 성능 저하를 가져야합니다. 그러나 이러한 성능 저하는 스레드를 사용하고 네트워크 훈련을 담당하는 스레드로 전달되기 전에 백그라운드에서 데이터를 보강하여 완화됩니다.

 

Data_Augmenation.tar.gz
0.44MB

'keras > 1.Data Augmentation' 카테고리의 다른 글

2. Flower-17  (0) 2020.08.20
1. Data Augmentation  (0) 2020.08.20

Flowers-17 데이터 세트

17 개의 서로 다른 꽃의 품종을 인식하는 세분화 된 분류 과제입니다. 이미지 데이터 세트는 매우 작으며 총 1,360개의 이미지에 대해 클래스 당 80개의 이미지 만 있습니다. 컴퓨터 비전 작업에 딥러닝을 적용 할 때 일반적인 경우는 클래스당 1,000 ~ 5,000개의 데이터를 갖는 것이므로 여기서는 확실히 큰 부족함이 있습니다.

모든 범주가 매우 유사하기 때문에 Flowers-17을 세분화 된 분류 작업이라고 부릅니다 (즉, 꽃의 품종). 사실, 우리는 이러한 각 범주를 하위 범주로 생각할 수 있습니다. 범주는 확실히 다르지만 상당한 양의 공통 구조를 공유합니다.

Flowers-17 데이터 세트의 5 개 (총 17 개 중) 클래스 샘플. 각 클래스는 특정 꽃의 종을 나타냅니다. (pyimagesearch)

세분화 된 분류 작업은 우리의 기계 학습 모델이 매우 유사한 클래스를 구별하기 위해 극도로 구별되는 기능을 학습해야 함을 의미하기 때문에 딥러닝 실무자에게 가장 어려운 경향이 있습니다. 이 세분화된 분류 작업은 제한된 훈련 데이터를 고려할 때 더욱 문제가됩니다.

 

Aspect-aware Preprocessing

지금까지는 영상비를 무시하고 고정 된 크기로 크기를 조정하여 이미지를 전처리했습니다. 일부 상황, 특히 기본 벤치 마크 데이터 세트의 경우 그렇게하는 것이 허용됩니다.

그러나 더 까다로운 데이터 세트의 경우 고정된 크기로 크기를 조정해야하지만 종횡비는 유지해야합니다. 

왼쪽 : 원본 입력 이미지 (410 × 310). 중간 : 가로 세로 비율을 무시하고 이미지 크기를 256 × 256 픽셀로 조정합니다. 이제 이미지가 찌그러지고 왜곡 된 것처럼 보입니다. 오른쪽 : 가로 세로 비율을 유지하면서 이미지 크기를 256 × 256으로 조정합니다.

왼쪽에는 고정 된 너비와 높이로 크기를 조정해야하는 입력 이미지가 있습니다. 가로 세로 비율을 무시하고 이미지 크기를 256 × 256 픽셀 (중간)로 조정하여 원하는 크기에 맞도록 이미지를 효과적으로 찌그러 뜨리고 왜곡합니다. 더 나은 접근 방식은 이미지의 종횡비 (오른쪽)를 고려하는 것입니다. 여기서 너비가 256 픽셀이되도록 더 짧은 치수를 따라 크기를 조정 한 다음 높이를 따라 이미지를 잘라 높이가 256 픽셀이되도록합니다.

자르는 동안 이미지의 일부를 효과적으로 버렸지 만 이미지의 원래 종횡비도 유지했습니다. 일관된 종횡비를 유지하면 Convolutional Neural Network가보다 차별적이고 일관된 기능을 학습 할 수 있습니다. 

aspect-aware 전처리가 어떻게 구현되는지 확인하기 위해 AspectAwarePreprocessor를 만들어보겠습니다.

생성자는 이미지 크기를 조정할 때 사용되는 보간 방법과 함께 두 개의 매개 변수 (대상 출력 이미지의 원하는 너비 및 높이)가 필요합니다. 

# import the necessary packages 
import imutils 
import cv2

class AspectAwarePreprocessor:
    def __init__(self, width, height, inter=cv2.INTER_AREA):
        # store the target image width, height, and interpolation
        # method used when resizing 
        self.width = width 
        self.height = height 
        self.inter = inter

 

그런 다음 아래에서 전처리 기능을 정의 할 수 있습니다.

    def preprocess(self, image):
        # grab the dimensions of the image and then initialize 
        # the deltas to use when cropping
        (h, w) = image.shape[:2] # 입력 이미지의 너비와 높이를 잡고

        # 더 큰 치수를 따라자를 때 사용할 델타 오프셋을 결정
        dW = 0
        dH = 0

즉, AspectAwarePreprocessor()는 2단계 알고리즘입니다.

1. Step # 1 : 가장 짧은 치수를 결정하고 이에 따라 크기를 조정합니다.
2. Step # 2 : 대상 너비와 높이를 얻기 위해 가장 큰 치수를 따라 이미지를 자릅니다.

다음 코드 블록은 너비가 높이보다 작은 지 확인하고, 그렇다면 너비를 따라 크기를 조정합니다.

        # if the width is smaller than the height, then resize 
        # along the width (i.e., the smaller dimension) and then 
        # update the deltas to crop the height to the desired # dimension        
        if w < h:
            image = imutils.resize(image, width=self.width, inter=self.inter)
            dH = int((image.shape[0] - self.height) / 2.0)

 

그렇지 않고 높이가 너비보다 작 으면 높이를 따라 크기를 조정합니다.

        else:
            image = imutils.resize(image, height=self.height, inter=self.inter)
            dW = int((image.shape[1] - self.width) / 2.0)

 

이제 이미지의 크기가 조정되었으므로 너비와 높이를 다시 잡고 델타를 사용하여 이미지 중앙을 잘라야합니다.

        # now that our images have been resized, we need to 
        # re-grab the width and height, followed by performing 
        # the crop
        (h, w) = image.shape[:2]
        image = image[dH:h - dH, dW:w - dW]

        # finally, resize the image to the provided spatial 
        # dimensions to ensure our output image is always a fixed 
        # size
        
        return cv2.resize(image, (self.width, self.height), interpolation=self.inter)

잘라낼 (반올림 오류로 인해) 이미지 대상 이미지 크기가 ± 1 픽셀만큼 벗어날 있습니다. 따라서 출력 이미지가 원하는 너비와 높이를 갖도록 cv2.resize 호출합니다. 그런 다음 전처리 이미지가 호출 함수로 반환됩니다. AspectAwarePreprocessor() 구현 했으므로 이제 Flowers-17 데이터 세트에서 MiniVGGNet 아키텍처를 학습 작동하도록하겠습니다.

 

aspectawarepreprocessor.py
0.00MB

 

 

'keras > 1.Data Augmentation' 카테고리의 다른 글

3. Flowers-17: With Data Augmentation  (0) 2020.08.21
1. Data Augmentation  (0) 2020.08.20

Goodfellow et al.에 따르면, 정규화는“일반화 오류를 줄이기위한 학습 알고리즘에 대한 모든 수정이지만 훈련 오류는 아닙니다" 다시 말해정규화는 훈련 오류를 약간 증가시키는 대신 테스트 오류를 ​​줄이려는 목적이 강합니다.

실무적으로는 다음과 같은 다른 유형의 정규화가 있습니다.

  1. 네트워크 아키텍처 자체를 수정합니다.
  2. 훈련을 위해 네트워크로 전달되는 데이터를 확장합니다.

 

드롭 아웃은 일반화 가능성을 높여 네트워크 아키텍처를 수정하는 좋은 예입니다. 여기에 이전 계층에서 다음 계층으로 노드를 무작위로 연결 해제하는 계층을 삽입하여 단일 노드가 주어진 클래스를 표현하는 방법을 모르게 합니다.

 

What is Data Augmentation?

 

Data Augmentation은 클래스 레이블이 변경되지 않도록 임의의 jitter 및 perturbation을 적용하여 원본에서 새로운 훈련 샘플을 생성하는 데 사용되는 광범위한 기술을 말합니다. Data Augmentation를 적용 할 때 우리의 목표는 모델의 일반화 가능성을 높이는 것입니다. 네트워크가 지속적으로 약간 수정 된 새 버전의 입력 데이터 포인트를 보고 있다는 점은 강력한 더 파워풀한 모델을 얻을 수 있음을 암시합니다. 테스트시에는 데이터 증대를 적용하지 않고 훈련 된 네트워크를 평가하지 않습니다. 대부분의 경우 훈련 정확도가 약간 떨어지더라도 테스트 정확도가 향상되는 것을 확인할 수 있습니다.

왼쪽 : 정확히 정규 분포를 따르는 250 개의 데이터 포인트 샘플. 오른쪽 : 소량의 무작위 "jitter"를 분포에 추가 이러한 유형의 데이터 증가는 네트워크의 일반화 가능성을 높일 수 있습니다. (pyimagesearch)

평균이 0이고 단위 분산이있는 정규 분포의 그림(왼쪽)을 생각해보겠습니다. 이 데이터에 대한 기계 학습 모델을 학습하면 분포를 정확하게 모델링 할 수 있지만 실제 애플리케이션에서는 데이터가 이러한 깔끔한 분포를 거의 따르지 않습니다.

대신 분류기의 일반화 가능성을 높이기 위해 무작위 분포 (오른쪽)에서 가져온 일부 값 ε을 추가하여 분포를 따라 무작위로 jitter 지점을 찾을 수 있습니다. 컴퓨터 비전에서 무작위와 같은 간단한 기하학적 변환을 적용하여 원본 이미지에서 추가 훈련 데이터를 얻을 수 있습니다.

 

1. Translations
2. Rotations
3. Changes in scale
4. Shearing
5. Horizontal (and in some cases, vertical) flips

 

이러한 변환의 (작은) 양을 입력 이미지에 적용하면 모양이 약간 변경되지만 클래스 레이블은 변경되지 않으므로 데이터 확장이 매우 자연스럽고 쉬운 방법이됩니다. 이런 방법은 컴퓨터 비전 작업을위한 딥 러닝에 적용합니다. 컴퓨터 비전에 적용되는 데이터 증대를위한보다 진보 된 기술에는 주어진 색 공간에서 색상의 randomized perturbation, nonlinear geometric distortions이 있습니다.

 

Visualizing Data Augmentation

# import the necessary packages
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import load_img
from imutils import paths
import argparse
import numpy as np

 

argparse() 모듈은 terminal에서 실행할 때 argument를 쉽게 parsing하는 모듈입니다. 일반적인 tool(ex. Pycharm, jupyter notebook)에서 직접적으로 실행하게 되면 error가 발생하게 됩니다.

# construct the argument parse ad parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True)
ap.add_argument("-o", "--output", required=True)
ap.add_argument("-p", "--prefix", type=str, default="image")
args = vars(ap.parse_args())

 

 

image를 불러오는 코드입니다.

print("[INFO] loading example image...")
image = load_img(args["image"])
image = img_to_array(image)
image = np.expand_dims(image, axis=0)  # 맨 앞 1차원 추가

 

 

애플리케이션에서 가장 많이 사용할 증가 매개 변수에 초점을 맞추겠습니다.
# rotation_range 매개 변수는 임의 회전의 각도 범위를 제어합니다. 여기에서 입력 이미지를 무작위로 ± 30도 회전 할 수 있습니다.
# width_shift_range 및 height_shift_range는 각각 수평 및 수직 이동에 사용됩니다. 매개 변수 값은 주어진 차원의 일부입니다 (이 경우 10 %).
# shear_range는 이미지를 기울일 수있는 라디안으로 시계 반대 방향의 각도를 제어합니다.
# 그런 다음 [1-zoom_range, 1 + zoom_range] 값의 균일 한 분포에 따라 이미지를 "확대" 또는 "축소"할 수 있는 포인트 값인 zoom_range가 있습니다.
# 마지막으로 horizontal_flip 논리값은 주어진 입력이 훈련 프로세스 동안 수평으로 전환될 여부를 체크합니다.
# 대부분의 컴퓨터 비전 응용 프로그램의 경우 이미지의 수평 플랩은 결과 클래스 레이블을 변경하지 않습니다.
# 우리의 목표는 입력 이미지를 약간 수정하여 클래스 레이블 자체를 변경하지 않고 새 학습 샘플을 생성하는 것이므로 이러한 유형의 데이터 증가를 적용 할 때 주의해야 합니다.

aug = ImageDataGenerator(
    rotation_range=30,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode="nearest",
)

 

 

생성된 Iterator로 이미지를 생성할 수 있습니다.

print("[INFO] generating images...")
imageGen = aug.flow(
    image,
    batch_size=1,
    save_to_dir=args["output"],
    save_prefix=args["prefix"],
    save_format="jpg",
)

total = 0
# 그런 다음 imageGen 생성기의 각 이미지를 반복하기 시작합니다. 
# 내부적으로 imageGen은 루프를 통해 요청 될 때마다 새로운 학습 샘플을 자동으로 생성합니다.
# 그런 다음 디스크에 기록 된 총 데이터 증가 예제 수를 늘리고 
# 예제 10 개에 도달하면 스크립트 실행을 중지합니다.
# loop over examples from our image data augmentation generator
for image in imageGen:
    # increment our counter
    total += 1

    # if we have reached 10 examples, break from the loop
    if total == 10:
        break

 

 

실행코드는 다음과 같습니다.

python augmentation.py -i jemma.png -o output -p image

데이터를 증폭할 원본 이미지
증폭된 강아지 이미지 사진 10개

각 이미지가 어떻게 무작위로 회전하고, 기울이고, 확대되고, 수평으로 튕겨져 있는지 확인합니다. 각각의 경우 이미지는 원래 클래스 레이블을 유지합니다.(dog); 그러나 각 이미지가 약간 수정되어 훈련 할 때 배울 수있는 새로운 패턴을 신경망에 제공합니다. 입력 이미지는 지속적으로 변경되기 때문에 (클래스 레이블은 동일하게 유지됨) 데이터 보강이없는 학습과 비교할 때 학습 정확도가 감소하는 것이 일반적입니다.

또한 Data Augmentation는 Overfitting을 줄이는 데 도움이 될 수 있으며, 동시에 모델이 새로운 입력 샘플에 더 잘 일반화되도록 보장합니다. 또한 딥러닝을 적용하기에는 예제가 너무 적은 데이터 세트로 작업 할 때 Data Augmentation을 활용하여 추가 훈련 데이터를 생성 할 수 있으므로 딥러닝 네트워크를 훈련하는 데 필요한 수동 레이블 데이터의 양을 줄일 수 있습니다.

augmentation.py
0.00MB
jemma.png
0.26MB

'keras > 1.Data Augmentation' 카테고리의 다른 글

3. Flowers-17: With Data Augmentation  (0) 2020.08.21
2. Flower-17  (0) 2020.08.20
word2vec(2)

word2vec

  • 단어를 벡터화할 때 단어의 문맥적 의미를 보존
In [1]:
from konlpy.tag import Kkma
from konlpy.utils import pprint
from gensim.models.word2vec import Word2Vec

import warnings
warnings.filterwarnings("ignore")


  • input data
  • 네이버 기사 로드
In [2]:
data = [["KB금융지주가 KB증권, KB캐피탈, KB부동산신탁 등 3개 계열사 대표를 새로 선정했다. 가장 큰 관심이 쏠렸던 KB증권 대표이사 후보에는 박정림 KB증권 부사장 겸 KB국민은행 부행장을 선정했다. 박 후보가 주주총회 등을 거쳐 최종 선임되면 금융투자업계 최초 여성 최고경영자(CEO)가 등장한다. KB금융은 19일 계열사 대표이사후보 추천위원회(이하 대추위)를 열고 KB증권·KB캐피탈·KB부동산신탁 등 7개 계열사 대표 후보를 선정했다고 밝혔다. KB증권 신임 대표이사 후보에는 박정림 KB증권 부사장 겸 KB국민은행 부행장과 김성현 KB증권 부사장을 추천했다. KB증권은 기존의 복수 대표체제를 유지한다. KB캐피탈에는 황수남 KB캐피탈 전무, KB부동산신탁에는 김청겸 KB국민은행 영등포 지역영업그룹대표가 각각 대표이사 후보로 선정됐다. 양종희 KB손해보험 대표, 조재민·이현승 KB자산운용 대표, 김해경 KB신용정보 대표는 재선정됐다. KB데이타시스템은 이른 시일 내에 적합한 인사를 찾아 추후 추천할 계획이다. 박정림 부사장이 KB증권 대표에 취임하면 증권사 최초로 여성 CEO가 탄생한다. 박 후보는 KB금융지주에서 WM(자산관리)과 리스크, 여신 등 요직을 두루 거쳤다. 그룹 WM 부문 시너지영업을 이끌며 리더십을 발휘하고 있다는 점을 높게 평가 받는다. 김성현 부사장은 대표적인 투자은행(IB) 전문가다. 투자자산 다변화를 통해 시장 지위를 바꿀 수 있는 리더십을 갖췄다는 평가를 받는다. 신임 대표는 20∼21일 계열사 대표이사후보 추천위원회의 최종 심사와 추천을 거쳐 주주총회에서 확정할 계획이다. 신임 대표 임기는 2년, 재선정 대표 임기는 1년이다."],
["서울 여의도에서 ‘카카오 카풀’에 반대하는 전국 택시업계 관계자들이 20일 대규모 집회를 벌인다. 택시기사 최 모 씨의 분신 등을 계기로 업계가 ‘총력투쟁’을 예고한 가운데 집회‧시위 시간이 출‧퇴근 시간과 겹쳐 이 시각 여의도 주변에 극심한 교통체증이 예상된다. 19일 경찰과 택시업계 등에 따르면 20일 오후 2시 전국택시노동조합연맹, 전국민주택시노동조합연맹, 전국개인택시운송사업조합연합회 등 4개 단체가 서울 여의도 국회 앞 의사당대로에서 3차 집회를 연다. 강신표 전국택시노동조합연맹 위원장은 집회를 하루 앞두고 열린 기자회견에서 “죽든지 살든지 총력 투쟁을 할 것”이라고 말했다. ‘국회를 포위하겠다던 기존 계획은 그대로 진행되느냐’는 질문에 강 위원장은 “그렇다”면서도 “만약 (경찰이) 막으면 할 수 없겠지만, 하는 데까지 최선을 다해 적폐 1호인 국회를 반드시 심판할 것”이라고 강조했다. 강 위원장은 “내일은 제주도를 포함한 전국의 택시가 운행을 중지한다”며 “앞으로 4차, 5차 집회 일정이 잡히면 그 날마다 택시 운행이 정지될 것”이라고 말했다. 이어 “자꾸 시민에게 불편을 드려죄송하지만 생존권을 지키기 위해 여의도 국회 앞에 모일 수밖에 없는 절박한 상황을 헤아려 주시길 바란다”고 덧붙였다."],
       ["'내보험 찾아줌' 홈페이지가 접속자 폭주로 인해 접속 대기시간이 길어지고 있다. 19일 오후 9시20분 현재 '내보험 찾아줌' 홈페이지에는 접속자 수가 몰리며 서비스 이용이 불가능한 상태다. 현재 사이트 접속자 수는 4641여명에 달한다. 금감원에 따르면 11월 말 기준 소비자가 찾아가지 않은 숨은 보험금은 약 9조8130억원인 것으로 나타났다.지난해 12월부터 지난달까지 숨은보험금 찾아주기 안내 활동을 통해 약 3조125억원(240만5000건)이 주인을 찾았다. 업권별로는 생명보험회사가 약 2조7907억원(222만건), 손해보험회사가 2218억원(18만 5000건)을 찾아줬다. 금감원은 20일부터 기존 '내보험 찾아줌' 서비스를 개선해 찾은 숨은보험금을 각 보험회사 온라인 청구시스템에 바로 접속할 수있도록 링크를 제공한다고 밝혔다. 기존 숨은 보험금 청구 시에는 소비자가 개별적으로 해당 보험회사 홈페이지, 콜센터, 계약 유지·관리 담당 설계사 등을 찾아 별도로 진행해야 하는 불편이 있었다. 앞으로는 '내보험 찾아줌' 홈페이지에 접속해 이름, 휴대폰 번호, 주민등록번호를 입력 후 휴대폰 인증을 거치면 생명보험 25개사, 손해보험 16개사 등 모두 41개 보험회사를 대상으로 숨은 보험금을 조회할 수 있다. 숨은 보험금이 있는 경우 해당 보험사에 보험금 지급청구를 하면 영업일 3일 이내 금액을 지급한다. 단 이미 보험금을 청구해 심사 중이거나 지급정지 등으로 청구할 수 없는 보험금은 조회되지 않는다."],
       ["KB증권은 김성현 KB증권 IB총괄 부사장과 박정림 KB증권 WM 부문 부사장을 신임 대표로 각각 선임했다고 19일 밝혔다. 윤경은, 전병조 대표이사가 자리에서 물러났지만 각자 대표이사 체제는 유지된다. 이는 WM과 IB의 부문을 각각 집중하기 위함으로 풀이된다. 특히 박 신임 대표는 증권업계 첫 여성 최고경영자(CEO)이다. 박 신임 대표는 서울대 경영학과·경영대학원 출신으로 1986년 체이스맨해튼 서울지점, 조흥은행, 삼성화재 등을 거쳐 2004년 처음으로 KB국민은행에 들어왔다. 당시 시장운영리스크 부장을 시작으로 2012년엔 WM본부장, 2014년 리스크관리그룹 부행장, 2015년 KB금융지주 리스크관리책임자 부사장 겸 리스크관리그룹 부행장을 맡았고 2016년엔 여신그룹 부행장을 맡았다. 작년부턴 KB금융 WM총괄 부사장 겸 은행 WM그룹 부행장 겸 KB증권 WM부문 부사장을 맡고 있다. KB금융지주는 박 신임 대표에 대해 WM, 리스크, 여신 등 폭넓은 업무 경험을 바탕으로 수익 확대에 대한 실행역량을 보유하고 있다고 밝혔다. 그룹 WM 부문의 시너지영업을 진두지휘하며 리더십을 발휘했다는 평가다. 현 IB총괄 부사장인 김성현 신임 대표는 IB부문을 총괄한다. 김 신임 대표이사는 연세대 경제학과를 졸업하고 1988년 대신증권에 입사한 이후 한누리투자증권을 거쳐 2008년 KB투자증권 기업금융본부장으로 임명됐다. 이후 2015년부터 KB투자증권 IB부문에서 일한 전문가다. KB금융지주는 김 신임 대표에 대해 IB 전문가로 투자자산 다변화 등을 통해 시장 지위를 개선시킬 수 있는 검증된 리더십을 보유했다고 평가했다."], 
        ["""서민금융진흥원은 지난 18일 서울 청계천로 본원에서 제2차 서민금융 전문가 간담회를 개최했다소 19일 밝혔다.

이번 간담회는 서민금융, 복지, 자활사업 등 각 분야 전문가들이 참석한 가운데, 정책서민금융 지원의 방향성에 대해서 의견을 청취하기 위해 마련됐다. 이날 이 원장은 "소득양극화와 고용부진 심화 등으로 서민·취약계층, 자영업자들의 경제적 어려움이 커지는 가운데 사회안전망으로서 서민금융의 역할이 중요한 시점"이라며, "현재 8등급 이하자가 263만명이고 이들중 74%가 연체중인 상황에서 정상적인 금융 이용이 어려운 취약계층에게 꼭 필요한 서민금융 지원을 위해 노력해야 한다"고 강조했다.

이어서 이 원장은 "현장 전문가의 의견을 반영하여 취약계층을 위한 금융과 함께 금융교육, 컨설팅, 종합상담 등 자활기반을 구축하도록 힘쓰겠다"고 밝혔다. 이날 참석자들은 '정책서민금융지원에 대한 방향성'에 대하여 다양한 의견을 제시했다.

진흥원은 이날 간담회의 다양한 제언들을 바탕으로 수요자가 체감할 수 있는 실질적인 방안 마련을 위해 더욱 노력하고, 지속적으로 서민금융 현장의 폭넓은 의견을 청취할 계획이다.
"""],
       ["""JB금융지주는 차기 회장 후보자로 김기홍 JB자산운용 대표(사진)를 선정했다.

19일 JB금융지주 임원후보추천위원회는 최종 후보군에 대해 PT발표와 심층면접을 진행한 후, 김 대표를 최종 후보자로 선정했다.

이날 PT발표와 심층면접에선 후보자의 JB금융그룹의 성장 비전과 전문성, 리더십, 기업의 사회적 책임 등 후보자의 역량에 대해 평가했으며, 김 대표는 은행을 비롯 보험사, 자산운용사 등 금융권 임원 경험을 바탕으로 금융 전반에 대한 전문적인 지식과 넓은 식견을 갖추고 있다는 점이 높이 평가됐다.

JB금융지주 임추위 관계자는 "김 후보자가 20년 이상 금융산업에 종사한 경험을 바탕으로 금융에 대한 전문적인 식견 뿐 만 아니라 리더십과 소통능력도 탁월하다"며 "급변하는 금융환경에 대응하고 계열사 간 시너지 창출을 통해 기업가치를 극대화하는 등 JB금융그룹을 최고의 소매전문 금융그룹으로 발전시킬 적임자"라고 밝혔다. 이에 따라 김 내정자는 내년 3월 정기주주총회와 이사회를 거쳐 대표이사 회장으로 선임 될 예정이다.
"""], 
        ["""1800만 근로자의 2018년 귀속 근로소득에 대한 연말정산 신고기간이 한 달여 앞으로 다가왔다.

올해 연말정산에는 중소기업 취업 청년에 대한 소득세 감면이 확대되고 도서·공연비 지출액에 대한 신용카드 사용액에 소득공제가 적용되는 등 새로운 기준이 적용되기 때문에 바뀐 공제 기준을 꼼꼼히 챙기는 것이 중요하다.

국세청은 올해 근로소득이 발생한 근로자는 내년 2월분 급여를 지급받을 때까지 연말정산을 신고해야 한다고 20일 밝혔다.

◇올해부터 달라지는 주요 공제 항목

올해 연말정산부터는 중소기업 취업 청년에 대한 소득세 감면을 받을 수 있는 대상 연령이 기존 29세에서 34세로 확대된다. 감면율도 70%에서 90%로 확대되고 감면 적용기간도 3년에서 5년으로 확대된다.

총급여액 7000만원 이하 근로자는 도서·공연비를 신용카드로 결제한 경우 해당 비용을 최대 100만원까지 추가 소득공제 받을 수 있다. 올 7월1일 이후 도서공연비로 지출한 금액의 소득공제율 30%가 적용되기 때문이다.

건강보험 산정특례 대상자로 등록된 부양가족을 위해 지출한 의료비는 기존 700만원 한도가 폐지되고 올해부터 전액공제를 받을 수 있게 됐다.

총급여액이 5500만원이거나 종합소득금액이 4000만원 초과 근로자의 경우 월세액 세액공제율이 10%에서 12%로 인상된다. 월세액 세액공제 한도는 750만원이며 임대차 계약서상 주소지와 계약기간 등 내역을 정확히 기재해야 공제를 받을 수 있다.

임차보증금 3억원 이하의 주택 임차보증금 반환 보증 보험료도 올해 연말정산부터 보험료 세액공제를 받을 수 있으며, 생산직 근로자의 초과근로수당 비과세 적용 시 기준이 되는 월정액 급여액은 150만원 이하에서 190만원 이하로 상향된다.

6세 이하 자녀 세액공제는 아동수당 지급에 따라 올해부터 폐지된다. 올 연말정산부터는 종교단체가 종교인에게 지급한 소득도 신고대상에 포함된다."""]
       ]


  • 한글 자연어 처리 클래스 적용
In [3]:
kkma = Kkma()
In [4]:
# kkma.sentences(data[0][0])

# sentences = [kkma.sentences(da[0]) for da in data]
# word_list = [[kkma.nouns(w) for w in sentence] for sentence in sentences]

# word_list
In [5]:
# word_list = []
# sentences = []
# for da in data:
# #     print(da)
#     sentences.append(kkma.sentences(da[0]))
#     for s in sentences:
#         for w in s:
#             for t in kkma.nouns(w):
#                 if len(t) >= 2:
#                     word_list.append(t)
# #             word_list.append(kkma.nouns(w))


  • word2vec으로 학습하기 위한 데이터 전처리
In [6]:
sentences = []
list_vec = []
for da in data:
#     print(da)
    sentences.append(kkma.sentences(da[0]))
    for s in sentences:
        for w in s:
            list_vec.append(kkma.nouns(w))
In [7]:
word_list = []
for l in list_vec:
    empty_vec = []
    for w in l:
        if len(w)>=2:
            empty_vec.append(w)   
    word_list.append(empty_vec)


  • modeling
In [8]:
# word_list

# word_list_tot = word_list[0]
# for i in range(len(word_list)-1):
#     word_list_tot = word_list_tot + word_list[i+1]

# word_list_tot

# sg : {0, 1}, optional
# Training algorithm: 1 for skip-gram; otherwise CBOW.
# size : embedding 차원
embedding_model = Word2Vec(word_list, size=100, window = 5, min_count=2, workers=3, iter=1000, sg=1, sample=1e-3)
In [9]:
# word_count = ["증권"]
# word_top = embedding_model.wv.most_similar(positive=["선임", "대표", "증권"], topn=10)
# word_top
# [w[0] for w in word_top]

# embedding_model.wv.distances("증권")

# embedding_model.wv.vectors.shape


  • 벡터화된 단어들로 Kmean Clustering
In [10]:
from sklearn.cluster import KMeans

word_vectors = embedding_model.wv.syn0 # 어휘의 feature vector
num_clusters = int(word_vectors.shape[0]/50) # 어휘 크기의 1/5나 평균 5단어
print(num_clusters)
num_clusters = int(num_clusters)
9
In [11]:
kmeans_clustering = KMeans(n_clusters=num_clusters)
idx = kmeans_clustering.fit_predict(word_vectors)

idx = list(idx)
names = embedding_model.wv.index2word
word_centroid_map = {names[i]: idx[i] for i in range(len(names))}


  • 결과 확인
In [12]:
for c in range(num_clusters):
    # 클러스터 번호를 출력
    print("\ncluster {}".format(c))
    
    words = []
    cluster_values = list(word_centroid_map.values())
    for i in range(len(cluster_values)):
        if (cluster_values[i] == c):
            words.append(list(word_centroid_map.keys())[i])            
    print(words)
cluster 0
['지급', '소득', '신용', '기준', '대상', '경우', '금액', '확대', '공제', '연말', '정산', '올해', '지급청구', '3일', '이내', '근로자', '적용', '세액', '내년', '근로', '기간', '감면', '도서', '공연비', '급여액', '근로소득', '신고', '중소기업', '취업', '청년', '소득세', '신용카드', '카드', '때문', '지출', '공제율', '한도', '폐지', '초과', '수당']

cluster 1
['택시', '집회', '전국', '위원장', '시너지', '택시업계', '총력', '투쟁', '경찰', '택시노동조합연맹', '노동', '조합', '연맹', '발휘', '오후', '이후', '주택', '포함', '대규모', '택시기사', '기사', '분신', '계기', '2시', '전국민', '전국민주택', '강신', '하루', '열린', '기자', '기자회견', '회견', '질문', '만약', '최선', '적폐', '1호', '심판', '내일', '제주', '제주도', '운행', '중지', '4차', '5차', '일정', '입력', '인증', '생명보험', '25', '25개', '집중', '풀이', '진두지휘', '1988', '1988년', '대신', '대신증권', '입사', '누리', '누리투자증권', '2008', '2008년', '급변', '금융환경', '환경', '대응', '창출', '기업가치', '가치', '극대화', '소매', '소매전문', '발전', '적임자']

cluster 2
['대표', '증권', '후보', '신임', '이사', '선정', '은행', '부사장', '투자', '20', '대표이사', '부문', '추천', '그룹', '업계', '19', '19일', '국민', '국민은행', '계열사', '영업', '부행장', '캐피탈', '부동산', '부동산신탁', '신탁', '박정', '여성', '주주', '총회', '최종', '추천위원회', '위원회', '주주총회', '최초', '대표이사후보', '선임', '최고', '이하', '심사', '총괄', '경영자', '체제', '3개', '관심', '금융투자업계', '등장', '대추', '7개', '복수', '영등포', '지역', '영업그룹', '박정림', '정림', '부사', '취임', '증권사', '탄생', '21', '확정', '임기', '2년', '1년', '전병', '자리', '각자', '증권업계', '서울대', '경영학과', '경영', '경영대학원', '연세대', '경제', '경제학과', '학과', '졸업', '회장', '내정자', '3월', '정기', '정기주주총회', '이사회', '예정']

cluster 3
['보험', '보험금', '기존', '내보험', '홈페이지', '회사', '청구', '20일', '손해', '유지', '관리', '접속자', '접속', '보험회사', '손해보험', '시스템', '해당', '서비스', '금감원', '소비자', '생명', '조회', '개선', '이용', '종희', '조재', '계약', '등록', '폭주', '대기', '9시', '20분', '수가', '불가능', '상태', '생명보험회사', '2조', '7907', '7907억원', '222', '만건', '온라인', '청구시스템', '링크', '제공', '개별적', '센터', '담당', '설계사', '별도', '이름', '휴대폰', '번호', '주민', '주민등록번호', '16', '개사', '41', '41개', '지급정지']

cluster 4
['가운데', '시간', '상황', '현재', '총력투쟁', '예고', '퇴근', '시각', '주변', '교통', '체증', '예상', '사이트', '4641', '여명', '중요', '자영업자', '경제적', '어려움', '사회', '안전망', '역할', '시점', '등급', '자가', '263', '263만명', '74', '연체', '중인', '정상적', '필요']

cluster 5
['금융', '전문가', '서민', '서민금융', '의견', '이날', '간담회', '지원', '18', '본부장', '2015', '2015년', '투자증권', '대표적', '진흥원', '자활', '정책', '방향성', '청취', '마련', '원장', '취약', '취약계층', '계층', '노력', '현장', '다양', '관리그룹', '관리책임자', '책임자', '2016', '2016년', '작년', '기업금융본부장', '임명', '종합', '18일', '청계', '천로', '본원', '2차', '개최', '이번', '복지', '자활사업', '분야', '참석', '양극화', '고용', '고용부진', '부진', '심화', '반영', '금융교육', '교육', '컨설팅', '종합상담', '상담', '참석자', '서민금융지원', '제시', '제언', '수요자', '체감', '실질적', '방안', '지속적']

cluster 6
['정지', '5000', '5000건', '수남', '전무', '12', '11', '11월', '9조', '8130', '8130억원', '지난해', '12월', '지난달', '주기', '안내', '활동', '3조', '125', '125억원', '240', '주인', '손해보험회사', '2218', '2218억원', '삼성', '화재', '2004', '2004년', '처음', '자활기반', '기반', '구축']

cluster 7
['여의도', '국회', '계획', '서울', '진행', '불편', '사업', '데이타', '데이타시스템', '시일', '적합', '인사', '추후', '단체', '카카오', '카풀', '반대', '노동조합연맹', '개인', '운송', '운송사업조합', '연합회', '4개', '의사당', '대로', '3차', '포위', '시민', '생존권', '대학원', '출신', '1986', '1986년', '체이스', '맨해튼', '서울지점', '지점', '조흥', '조흥은행', '당시', '시장운영', '운영', '부장', '시작', '2012', '2012년', '2014']

cluster 8
['지주', '자산', '리더십', '평가', '리스크', '여신', '시장', '자산운용', '운용', '투자자산', '다변화', '지위', '바탕', '관계자', '경험', '보유', '기업', '후보자', '김해경', '신용정보', '정보', '재선', '자산관리', '요직', '보험사', '역량', '업무', '수익', '실행', '검증', '임원', '발표', '심층', '면접', '금융그룹', '전문', '전문적', '식견', '차기', '사진', '임원후보', '성장', '비전', '사회적', '책임', '금융권', '전반', '지식', '추위', '20년', '이상', '금융산업', '산업', '종사', '소통', '소통능력', '능력']


  • word2vec을 100차원으로 했기 때문에 시각화를 위해서 2차원으로 축소,
  • 축소할 때 관계를 유지하기 위해 t-SNE로 transform
In [13]:
from sklearn.manifold import TSNE
import matplotlib.font_manager as fm
import matplotlib.pyplot as plt
import matplotlib

path_gothic = "/home/ururu/fonts/NanumGothic.ttf"
prop = fm.FontProperties(fname=path_gothic)
matplotlib.rcParams["axes.unicode_minus"] = False
In [14]:
vocab = list(embedding_model.wv.vocab)
X = embedding_model[vocab]

tsne = TSNE(n_components=2)
X_tsne = tsne.fit_transform(X) 
In [15]:
import pandas as pd

df = pd.DataFrame(X_tsne, index=vocab, columns=["x", "y"])
In [16]:
df.head()
Out[16]:
x y
금융 -8.060934 -1.692813
지주 -11.529280 -6.778675
증권 -9.415570 -0.928613
캐피탈 -10.257173 1.668560
부동산 -10.782980 1.529749
In [17]:
%matplotlib inline

fig = plt.figure()
fig.set_size_inches(40, 20)
ax = fig.add_subplot(1, 1, 1)
ax.scatter(df["x"], df["y"])

for word, pos in list(df.iterrows()):
    ax.annotate(word, pos, fontsize=12, fontproperties=prop)
plt.show()


classification

In [18]:
# embedding_model.wv.save_word2vec_format("word2vec.txt")
vectors = embedding_model.wv.vectors
names = embedding_model.wv.index2word


  • distance matrix
In [19]:
from scipy.spatial import distance_matrix
distance = distance_matrix(vectors, vectors)

distance_df = pd.DataFrame(distance, columns=names, index=names)
In [20]:
# 금융, 부동산, 보험
# distance_df.loc[vecs, :]


  • Term Document Matrix
In [21]:
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
In [22]:
word_data = []
for word in word_list:    
    for argu in word:
        word_data.append(argu)
In [23]:
vec = CountVectorizer()
X = vec.fit_transform(set(word_data))
In [24]:
TDM_DF = pd.DataFrame(X.toarray(), columns=vec.get_feature_names()).T

TDM_DF = TDM_DF.sum(axis=1).to_frame()
TDM_DF.rename(columns={0:"doc1"}, inplace=True)
TDM_DF.head()

idx_bool = TDM_DF["doc1"] >= 1
TDM_DF[idx_bool] = 1
In [25]:
TDM_matrix = TDM_DF.loc[names].values
distance_df_matrix = distance_df


  • labeling
In [26]:
classification_word = ["금융", "부동산", "보험", "은행", "카드", "증권"]
# wanted_word = ["금융", "부동산", "보험"]

target_matrix = distance_df.loc[classification_word,:].values


  • vector inner product로 최대값을 구하여 분류
In [27]:
import numpy as np

result = np.matmul(target_matrix, TDM_matrix)
maxpool = np.argmax(result)
classification_rlt = classification_word[maxpool]

print("classification result: {}".format(classification_rlt))
classification result: 은행
In [28]:
from IPython.core.display import display, HTML

display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

18.word2vec  (0) 2018.12.19
17.seq2seq  (0) 2018.12.19
16.RNN_word_autoComplete  (0) 2018.12.18
15.RNN_mnist  (1) 2018.12.18
14.gan  (0) 2018.12.16
18.word2vec

word2vec

In [1]:
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
In [2]:
# 단어 벡터를 분석해볼 임의의 문장들
sentences = ["나 우루루다",
             "나 강아지 좋다",
             "나 동물 좋다",
             "강아지 고양이 동물",
             "나 고양이 싫다"
             "강아지 여자친구 좋다", 
             "강아지 생선 우유 싫다",
             "고양이 생선 싫다 우유 좋다",
             "강아지 고양이 눈 좋다",
             "나 여자친구 좋다",
             "여자친구 나 좋다",
             "여자친구 나 영화 책 게임 좋다",
             "나 게임 만화 애니 좋다",
             "고양이 강아지 싫다",
             "강아지 고양이 좋다"]


  • 문장을 전부 합친 후 공백으로 단어들을 나누고 고유한 단어들로 리스트를 만듬
In [3]:
word_sequence = " ".join(sentences).split()
word_list = " ".join(sentences).split()
word_list = list(set(word_list))


  • 문자열로 분석하는 것 보다, 숫자로 분석하는 것이 훨씬 용이
  • 리스트에서 문자들의 인덱스를 뽑아서 사용하기 위해,
  • 이를 표현하기 위한 연관 배열과, 단어 리스트에서 단어를 참조 할 수 있는 인덱스 배열을 만듬
In [4]:
# word: index
word_dict = {w: i for i, w in enumerate(word_list)}


  • 윈도우 사이즈를 1 로 하는 skip-gram 모델을 만듬
  • 예) 나 게임 만화 애니 좋다
    -> ([나, 만화], 게임), ([게임, 애니], 만화), ([만화, 좋다], 애니)
    -> (게임, 나), (게임, 만화), (만화, 게임), (만화, 애니), (애니, 만화), (애니, 좋다)
In [5]:
skip_grams = []

for i in range(1, len(word_sequence) - 1):
    # (context, target) : ([target index - 1, target index + 1], target)
    # 스킵그램을 만든 후, 저장은 단어의 고유 번호(index)로 저장
    target = word_dict[word_sequence[i]]
    context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]

    # (target, context[0]), (target, context[1])..
    for w in context:
        skip_grams.append([target, w])


# skip-gram 데이터에서 무작위로 데이터를 뽑아 입력값과 출력값의 배치 데이터를 생성하는 함수
def random_batch(data, size):
    random_inputs = []
    random_labels = []
    random_index = np.random.choice(range(len(data)), size, replace=False)

    for i in random_index:
        random_inputs.append(data[i][0])  # target
        random_labels.append([data[i][1]])  # context word

    return random_inputs, random_labels
In [6]:
training_epoch = 1000
learning_rate = 0.01
batch_size = 20

# 단어 벡터를 구성할 임베딩 차원의 크기
# 이 예제에서는 x, y 그래프로 표현하기 쉽게 2 개의 값만 출력
embedding_size = 2

# word2vec 모델을 학습시키기 위한 nce_loss 함수에서 사용하기 위한 샘플링 크기
# batch_size 보다 작아야
num_sampled = 15

# 총 단어 갯수
voc_size = len(word_list)
In [7]:
inputs = tf.placeholder(tf.int32, shape=[batch_size])

# tf.nn.nce_loss 를 사용하려면 출력값을 [batch_size, 1] 구성
labels = tf.placeholder(tf.int32, shape=[batch_size, 1])

# word2vec 모델의 결과 값인 임베딩 벡터를 저장할 변수
# 총 단어 갯수와 임베딩 갯수를 크기로 하는 두 개의 차원을 갖음
embeddings = tf.Variable(tf.random_uniform([voc_size, embedding_size], -1.0, 1.0))

# 임베딩 벡터의 차원에서 학습할 입력값에 대한 행들을 뽑음
# 예) embeddings     inputs    selected
#    [[1, 2, 3]  -> [2, 3] -> [[2, 3, 4]
#     [2, 3, 4]                [3, 4, 5]]
#     [3, 4, 5]
#     [4, 5, 6]]
selected_embed = tf.nn.embedding_lookup(embeddings, inputs)

# nce_loss 함수에서 사용할 변수들을 정의
nce_weights = tf.Variable(tf.random_uniform([voc_size, embedding_size], -1.0, 1.0))
nce_biases = tf.Variable(tf.zeros([voc_size]))

# nce_loss 함수를 직접 구현하려면 매우 복잡하지만,
# 함수를 텐서플로우가 제공하므로 그냥 tf.nn.nce_loss 함수를 사용
loss = tf.reduce_mean(
            tf.nn.nce_loss(nce_weights, nce_biases, labels, selected_embed, num_sampled, voc_size))

train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)
In [8]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

loss_val_list = []
for step in range(1, training_epoch+1):
    batch_inputs, batch_labels = random_batch(skip_grams, batch_size)
    _, loss_val = sess.run([train_op, loss],
                           feed_dict={inputs: batch_inputs,
                                      labels: batch_labels})
    
    loss_val_list.append(loss_val)

    if step % 200 == 0:
        print("loss at step, step: {}: {}".format(step, loss_val))

    # matplot 으로 출력하여 시각적으로 확인해보기 위해
    # 임베딩 벡터의 결과 값을 계산하여 저장
    # with 구문 안에서는 sess.run 대신 간단히 eval() 함수를 사용
trained_embeddings = sess.run(embeddings, feed_dict={inputs: batch_inputs,
                                                     labels: batch_labels})
loss at step, step: 200: 3.1223583221435547
loss at step, step: 400: 3.23138165473938
loss at step, step: 600: 3.411635637283325
loss at step, step: 800: 2.716653347015381
loss at step, step: 1000: 2.981886625289917
In [9]:
plt.figure(figsize=(20, 7))
plt.title("cost")
plt.plot(loss_val_list, linewidth=0.7)
plt.show()
In [10]:
# matplotlib 한글 표시
import matplotlib.font_manager as fm

path_gothic = "/home/ururu/fonts/NanumGothic.ttf"
prop = fm.FontProperties(fname=path_gothic)
In [11]:
# 임베딩된 Word2Vec 결과 확인
# 결과는 해당 단어들이 얼마나 다른 단어와 인접해 있는지를 보여줌
plt.figure(figsize=(20, 7))
for i, label in enumerate(word_list):
    x, y = trained_embeddings[i]
    plt.scatter(x, y)
    plt.annotate(label, xy=(x, y), xytext=(5, 2),
                 textcoords='offset points', ha='right', va='bottom', fontproperties=prop)


plt.show()
In [12]:
from IPython.core.display import HTML, display

display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

19.word2vec  (0) 2018.12.20
17.seq2seq  (0) 2018.12.19
16.RNN_word_autoComplete  (0) 2018.12.18
15.RNN_mnist  (1) 2018.12.18
14.gan  (0) 2018.12.16
17.seq2seq

sequence to sequence

  • seq2seq는 RNN과 출력하는 신경망을 조합한 모델
  • 번역이나 챗봇 등 문장을 입력받아 다른 문장을 출력하는 프로그램에서 많이 사용

  • seq2seq모델은 인코더와 디코더로 구성
    • encoder는 원문을, decoder는 encoder의 결과물
    • 후에 decoder가 출력한 결과물을 번역한 결과물과 비교하면서 학습

  • symbol:
  • decoder에 입력이 시작됨을 알려주는 symbol
  • decoder의 출력이 끝났음을 알려주는 symbol
  • 빈 데이터를 채울 때 사용하는 아무 의미가 없는 symbol
In [1]:
import tensorflow as tf
import numpy as np

char_arr = [c for c in "SEPabcdefghijklmnopqrstuvwxyz단어나무놀이소녀키스사랑봉구우루"]
num_dic = {n: i for i, n in enumerate(char_arr)}
dic_len = len(num_dic)

seq_data = [['word', "단어"], ["wood", "나무"], ["game", "놀이"], ["girl", "소녀"], 
            ["kiss", "키스"], ["love", "사랑"], ["bong", "봉구"], ["uruu", "우루"]]
In [2]:
def make_batch(seq_data):
    input_batch = []
    output_batch = []
    target_batch = []
    
    for seq in seq_data:
        input = [num_dic[n] for n in seq[0]]
        output = [num_dic[n] for n in ("S" + seq[1])]
        target = [num_dic[n] for n in (seq[1] + "E")]
        
        input_batch.append(np.eye(dic_len)[input])
        output_batch.append(np.eye(dic_len)[output])
        target_batch.append(target)
        
    return input_batch, output_batch, target_batch
In [3]:
learning_rate = 0.001
n_hidden = 128
total_epoch = 1000

n_class = n_input = dic_len
In [4]:
enc_input = tf.placeholder(tf.float32, [None, None, n_input])
dec_input = tf.placeholder(tf.float32, [None, None, n_input])
targets = tf.placeholder(tf.int64, [None, None])
In [5]:
# encoder: [batch size, time steps, input size]
# decoder: [batch size, time steps]

with tf.variable_scope("encode"):
    enc_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
    enc_cell = tf.nn.rnn_cell.DropoutWrapper(enc_cell, output_keep_prob=0.5)
    
    outputs, enc_states = tf.nn.dynamic_rnn(enc_cell, enc_input, dtype=tf.float32)
    
with tf.variable_scope("decode"):
    dec_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
    dec_cell = tf.nn.rnn_cell.DropoutWrapper(enc_cell, output_keep_prob=0.5)
    
    outputs, dec_stats = tf.nn.dynamic_rnn(dec_cell, dec_input, 
                                           initial_state=enc_states, dtype=tf.float32)
WARNING:tensorflow:From <ipython-input-5-2da500f4b7bd>:5: BasicRNNCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This class is equivalent as tf.keras.layers.SimpleRNNCell, and will be replaced by that in Tensorflow 2.0.
In [6]:
model = tf.layers.dense(outputs, n_class, activation=None)
cost = tf.reduce_mean(
    tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=model, labels=targets
    )
)
opt = tf.train.AdamOptimizer(learning_rate).minimize(cost)
In [7]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

input_batch, output_batch, target_batch = make_batch(seq_data)

cost_val = []
for epoch in range(total_epoch):
    _, loss = sess.run([opt, cost], feed_dict={enc_input: input_batch,
                                               dec_input: output_batch,
                                               targets: target_batch})
    cost_val.append(loss)
    
    if (epoch+1) % 200 ==0:
        print("Epoch: {:04d}, cost: {}".format(epoch+1, loss))
    
    
print("\noptimization complete")
Epoch: 0200, cost: 0.05466647818684578
Epoch: 0400, cost: 0.013100271113216877
Epoch: 0600, cost: 0.0049271308816969395
Epoch: 0800, cost: 0.002698158845305443
Epoch: 1000, cost: 0.0030308999121189117

optimization complete
In [9]:
import matplotlib.pyplot as plt
plt.rcParams["axes.unicode_minus"] = False

plt.figure(figsize=(20, 10))
plt.title("cost")
plt.plot(cost_val, linewidth=1, alpha=0.8)
plt.show()


  • 입력으로 word를 받았다면 seq_data는 ["word", "PPPP"]로 구성될 것
  • input_batch는 ["w", "o", "r", "d"], outout_batch는 ["P", "P", "P", "P"]글자들의 인덱스를 one-hot encoding한 값
  • target_batch는 각 글자의 인덱스인 [2, 2, 2 ,2]가 될 것

  • [batch_size, time step, input size]형태로 나오기 때문에 3번째 차원을 argmax로 취함


  • 예측 결과는 글자의 인덱스를 뜻하는 숫자이므로 각 숫자에 해당하는 글자를 가져와 배열을 만듬
  • 그리고 출력의 끝을 의미하는 "E"이후의 글자들을 제거하고 문자열로 만듬
  • decoder의 입력(time steps) 크기만큼 출력값이 나오므로 최종 결과는 ["사", "랑", "E", "E"]처럼 나오기 때문
In [10]:
def translate(word):
    seq_data = [word, "P" * len(word)]
    
    input_batch, output_batch, target_batch = make_batch([seq_data])
    prediction = tf.argmax(model, 2)
    
    result = sess.run(prediction, feed_dict={enc_input: input_batch,
                                             dec_input: output_batch,
                                             targets: target_batch})
    decoded = [char_arr[i] for i in result[0]]
    
    try:
        end = decoded.index("E")
        translated = "".join(decoded[:end])
        return translated
        
    except Exception as ex:
        pass
In [21]:
print("\n ==== translate test ====")

print("word -> {}".format(translate("word")))
print("wodr -> {}".format(translate("wodr")))
print("love -> {}".format(translate("love")))
print("loev -> {}".format(translate("loev")))
print("bogn -> {}".format(translate("bogn")))
print("uruu -> {}".format(translate("uruu")))
print("abcd -> {}".format(translate("abcd")))
 ==== translate test ====
word -> 단어
wodr -> 나무
love -> 사랑
loev -> 사랑
bogn -> 봉구
uruu -> 우루
abcd -> 이
In [12]:
from IPython.core.display import HTML, display

display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

19.word2vec  (0) 2018.12.20
18.word2vec  (0) 2018.12.19
16.RNN_word_autoComplete  (0) 2018.12.18
15.RNN_mnist  (1) 2018.12.18
14.gan  (0) 2018.12.16
16.RNN_word_autoComplete

word auto complete

  • 염문자 4개를 학습시켜 3글자만 주어지면 나머지 한 글자를 추처하여 단어를 완성
  • dynamic_rnn의 sequence_length 옵션을 사용하면 가변 길이 단어를 학습시킬 수 있음
  • 짧은 단어는 가장 긴 단어의 길이 만큼 뒷부분을 0으로 채우고, 해당 단어의 길이를 계산해 (batch_size)만큼의 배열로 sequence_length로 넘겨주면 됨


  • 학습시킬 데이터는 영문자로 구성된 임의의 단어를 사용할 것이고, 한 글자 한글자를 하나의 단계로 봄
  • 한글자가 한 단계의 입력값이 되고, 총 글자 수가 전체 단계가 됨
  • 입력으로는 알파벳 순서에서 각 글자에 해당하는 인덱스를 one-hot encoding으로 표현한 값을 취함
In [1]:
import tensorflow as tf
import numpy as np
In [2]:
char_arr = ["a", "b", "c", "d", "e", "f", "g",
            "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u",
            "v", "w", "x", "y", "z"]

num_dic = {n: i for i, n in enumerate(char_arr)}
dic_len = len(num_dic)
In [3]:
seq_data = ["word", "wood", "deep", "dive", "cold", "cool", "load", "love", "kiss", "kind"]


utiliy function

  • "deep"는 입력으로 "d", "e", "e"를 취하고, 각 알파벳의 인덱스를 구해 배열로 만들면 [3, 4, 4]가 됨
  • 이를 one-hot encoding
In [4]:
def make_batch(seq_data):
    input_batch = []
    target_batch = []
    
    for seq in seq_data:
        input = [num_dic[n] for n in seq[:-1]]
        target = num_dic[seq[-1]]
        input_batch.append(np.eye(dic_len)[input])
        target_batch.append(target)
        
    return input_batch, target_batch


hyper parameter setting

  • 단어의 전체중 처음 3글자를 단계적으로 학습할 것이므로 n_step=3
  • 입력값과 출력값은 one-hot encoding을 사용하므로 dic_len과 같음
  • sparse_softmax_cross_entropy_with_logits 함수를 사용하더라도 예측 모델의 출력값은 one-hot encoding을 해야함
  • sparse_softmax_cross_entropy_with_logits 함수를 사용할 때 실측값인 labels의 값은 인덱스의 숫자를 그대로 사용하고, 예측 모델의 출력값은 인덱스의 one-hot encoding을 사용
In [5]:
learning_rate = 0.001
n_hidden = 128
total_epoch = 10000

n_step = 3
n_input = n_class = dic_len


variable setting

  • Y의 placeholder는 batch_size에 해당하는 하나의 차원만 있음
In [6]:
X = tf.placeholder(tf.float32, [None, n_step, n_input], name="input_X")
Y = tf.placeholder(tf.int32, [None])

W = tf.Variable(tf.random_normal([n_hidden, n_class]))
b = tf.Variable(tf.random_normal([n_class]))


model setting

  • RNN cell 2개 생성
  • DropoutWrapper를 이용하여 RNN에도 overfitting 방지
In [7]:
cell1 = tf.nn.rnn_cell.BasicLSTMCell(n_hidden)
cell1 = tf.nn.rnn_cell.DropoutWrapper(cell1, output_keep_prob=0.5)
cell2 = tf.nn.rnn_cell.BasicLSTMCell(n_hidden)

# MultiRNNCell 함수를 사용하여 조합
multi_cell = tf.nn.rnn_cell.MultiRNNCell([cell1, cell2])
outputs, states = tf.nn.dynamic_rnn(multi_cell, X, dtype=tf.float32)
WARNING:tensorflow:From <ipython-input-7-06df5d391133>:1: BasicLSTMCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This class is deprecated, please use tf.nn.rnn_cell.LSTMCell, which supports all the feature this cell currently has. Please replace the existing code with tf.nn.rnn_cell.LSTMCell(name='basic_lstm_cell').
In [8]:
outputs = tf.transpose(outputs, [1, 0, 2])
outputs = outputs[-1]
model = tf.matmul(outputs, W) + b


modeling

In [9]:
cost = tf.reduce_mean(
    tf.nn.sparse_softmax_cross_entropy_with_logits(logits=model, labels=Y)   
)
opt = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
In [10]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

input_batch, output_batch = make_batch(seq_data)

cost_epoch = []
for epoch in range(total_epoch):
    _, loss = sess.run([opt, cost], feed_dict={X: input_batch, Y: output_batch})
    cost_epoch.append(loss)
    
    if (epoch+1) % 2000 ==0:
        print("Epoch: {}, cost= {}".format(epoch+1, loss))
        
print("\noptimization complete")
Epoch: 2000, cost= 1.4388267118192744e-05
Epoch: 4000, cost= 8.106222821879783e-07
Epoch: 6000, cost= 3.695482178045495e-07
Epoch: 8000, cost= 1.323218612014898e-06
Epoch: 10000, cost= 1.4305105366929638e-07

optimization complete
In [16]:
import matplotlib.pyplot as plt

plt.rcParams["axes.unicode_minus"] = False
plt.figure(figsize=(20,6))
plt.title("cost")
plt.plot(cost_epoch, linewidth=1)
plt.show()


  • 실측값을 원-핫 인코딩이아닌 인덱스를 그대로 사용
In [12]:
prediction = tf.cast(tf.argmax(model, 1), tf.int32)
prediction_check = tf.equal(prediction, Y)
accuracy = tf.reduce_mean(tf.cast(prediction_check, tf.float32))

prediction

  • prediction model
In [13]:
input_batch, target_batch = make_batch(seq_data)

predict, accuracy_val = sess.run([prediction, accuracy], 
                                 feed_dict={X: input_batch, Y: target_batch})


  • predict
In [14]:
predict_word = []
for idx, val in enumerate(seq_data):
    last_char = char_arr[predict[idx]]
    predict_word.append(val[:3] + last_char)
    
print("\n==== prediction ====")
print("input_value: \t\t{}".format([w[:3] for w in seq_data]))
print("prediction_value: \t{}".format(predict_word))
print("accuracy: {:.3f}".format(accuracy_val))
==== prediction ====
input_value: 		['wor', 'woo', 'dee', 'div', 'col', 'coo', 'loa', 'lov', 'kis', 'kin']
prediction_value: 	['word', 'wood', 'deep', 'dive', 'cold', 'cool', 'load', 'love', 'kiss', 'kind']
accuracy: 1.000
In [15]:
from IPython.core.display import HTML, display

display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

18.word2vec  (0) 2018.12.19
17.seq2seq  (0) 2018.12.19
15.RNN_mnist  (1) 2018.12.18
14.gan  (0) 2018.12.16
13.auto-encoder  (0) 2018.12.15
15.RNN_mnist

  • 이 그림의 가운데에 있는 한 덩어리의 신경망을 RNN에서는 Cell이라 부름
  • cell을 여러개 중첩하여 심층 신경망을 만듬
  • 앞 단계에서 학습한 결과를 다음 단계의 학습에 이용
  • 따라서 학습 데이터를 단계별로 구분하여 입력

  • 사람은 글씨를 위에서 아래로 내려가면서 쓰는 경향이 많으므로
  • 가로 한줄의 28 픽셀을 한 단계의 입력값으로 삼고
  • 세로줄이 총 28개 이므로 28단계를 거쳐 데이터를 입력 받음


library load

In [1]:
import tensorflow as tf
import numpy as np
In [3]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
Extracting ./mnist/data/train-images-idx3-ubyte.gz
Extracting ./mnist/data/train-labels-idx1-ubyte.gz
Extracting ./mnist/data/t10k-images-idx3-ubyte.gz
Extracting ./mnist/data/t10k-labels-idx1-ubyte.gz


hyper parameter

  • 입력값 X에 n_step이라는 차원을 하나 더 추가
  • RNN은 순서가 있는 데이터를 다루므로 한 번에 입력 받을 갯수와 몇 단계로 이뤄진 데이터를 받을지를 설정
  • 가로 픽셀 수를 n_input, 세로 픽셀 수를 입력 단계인 n_step으로 설정
  • 앞에서 설명한 대로 RNN은 순서가 있는 데이터를 다루므로 한 번에 입력 받을 갯수와 총 몇 단계로 이뤄진 데이터를 받을지를 설정
  • 가로 픽셀수: n_input, 세로 픽셀수: n_step
  • 출력값은 계속해서 온 것처럼 MNIST의 분류인 0~9까지 10개의 숫자를 one-hot encoding으로 표현
In [4]:
learning_rate = 0.001
total_epoch = 30
batch_size = 128

n_input = 28
n_step = 28
n_hidden = 128
n_class = 10

X = tf.placeholder(tf.float32, [None, n_step, n_input], name="input_X")
Y = tf.placeholder(tf.float32, [None, n_class], name="output_Y")
W = tf.Variable(tf.random_normal([n_hidden, n_class], name="weight_W"))
b = tf.Variable(tf.random_normal([n_class], name="bias_b"))


hidden개의 출력값을 갖는 RNN cell을 생성

In [5]:
cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
WARNING:tensorflow:From <ipython-input-5-e006f918b220>:1: BasicRNNCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This class is equivalent as tf.keras.layers.SimpleRNNCell, and will be replaced by that in Tensorflow 2.0.
  • BasicLSTMCell, GRUCell 등 다양한 방식의 셀을 사용
  • RNN의 기본신경망은 긴 단계의 데이터를 학습할 때 맨 뒤에서는 맨 앞의 정보를 잘 기억하지 못하는 특성이 존재
  • 이를 보완하기 나온 것이 LSTMLong Short-Term Memory, GRUGated Recurrent Units
  • GRU는 LSTM과 비슷하지만, 구조가 조금 더 간단한 신경망 Architecture


complete RNN

In [6]:
outputs, states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)


  • 결과값을 one-hot encoding 형태로 만들 것이므로 손실 함수로 tf.nn.softmax_cross_entropy_with_logits_v2를 사용
  • 이 함수를 사용하려면 최종 결과값이 [batch_size, n_class] 여야 함
  • RNN 신경망에서 나오는 출력값은 [batch_size, n_step, n_hidden]
In [7]:
# outputs : [batch_size, n_step, n_hidden]
outputs = tf.transpose(outputs, [1, 0, 2]) # index를 기준으로 transpose
outputs = outputs[-1]


modeling

$y = (X \times W) +b$

In [8]:
model = tf.matmul(outputs, W) + b
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
opt = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)


variable initializer

In [9]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
In [10]:
x_train = mnist.train.images
y_train = mnist.train.labels
In [11]:
class Dataset:
    def __init__(self, x, y):
        self.index_in_epoch = 0
        self.epoch_completed = 0
        self.x_train = x
        self.y_train = y
        self.num_examples = x.shape[0]
        
    def data(self):
        return self.x_train, self.y_train
    
    def next_batch(self, batch_size):
        start = self.index_in_epoch
        self.batch_size = batch_size
        self.index_in_epoch += self.batch_size
        
        if start==0 and self.epoch_completed==0:
            idx = np.arange(self.num_examples)
            np.random.shuffle(idx)
            self.x_train = self.x_train[idx]
            self.y_train = self.y_train[idx]
            
        if start + batch_size > self.num_examples:            
            self.epoch_completed += 1
            
            perm = np.arange(self.num_examples)
            np.random.shuffle(perm)
            self.x_train = self.x_train[perm]
            self.y_train = self.y_train[perm]

            start = 0
            self.index_in_epoch = self.batch_size

        end = self.index_in_epoch
        return self.x_train[start:end], self.y_train[start:end]
In [12]:
total_batch = int(x_train.shape[0]/batch_size)
epoch_cost_val_list = []
cost_val_list = []
for epoch in range(total_epoch):
    epoch_cost = 0
    for i in range(total_batch):
        batch_xs, batch_ys = Dataset(x=x_train, y=y_train).next_batch(batch_size=batch_size)
        batch_xs = batch_xs.reshape([batch_size, n_step, n_input])
        
        _, cost_val = sess.run([opt, cost], feed_dict={
            X: batch_xs, Y: batch_ys
        })
        
        epoch_cost += cost_val
        cost_val_list.append(cost_val)        
        
    epoch_cost_val_list.append(epoch_cost)   
    
    if (epoch+1) %5 == 0:
        print("Epoch: %04d" % (epoch+1),
              "Avg.cost = {}".format(epoch_cost/total_batch))
    
print("\noptimization complete")

is_correct = tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))

test_batch_size = len(mnist.test.images)
test_xs = mnist.test.images.reshape(test_batch_size, n_step, n_input)
test_ys = mnist.test.labels

print("\naccuracy {:.3f}%".format(
    sess.run(accuracy*100, feed_dict={X: test_xs, Y: test_ys})
))
Epoch: 0005 Avg.cost = 0.13626715096716696
Epoch: 0010 Avg.cost = 0.0966348738251102
Epoch: 0015 Avg.cost = 0.08380235770244003
Epoch: 0020 Avg.cost = 0.07091071723204861
Epoch: 0025 Avg.cost = 0.07897876071068513
Epoch: 0030 Avg.cost = 0.05630091918466313

optimization complete

accuracy 97.660%
In [14]:
import matplotlib.pyplot as plt

plt.rcParams["axes.unicode_minus"] = False

_, ax = plt.subplots(1, 2, figsize=(20, 5))
ax[0].set_title("cost_epoch")
ax[0].plot(epoch_cost_val_list, linewidth=0.3)
ax[1].set_title("cost_value")
ax[1].plot(cost_val_list, linewidth=0.3)
plt.show()
In [16]:
from IPython.core.display import HTML, display

display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

17.seq2seq  (0) 2018.12.19
16.RNN_word_autoComplete  (0) 2018.12.18
14.gan  (0) 2018.12.16
13.auto-encoder  (0) 2018.12.15
12.mnist_cnn  (0) 2018.12.12
14.gan

GAN

GANGenerative Adversarial Network

  • 서로 대립adversarial하는 두 신경망을 경쟁시켜가며 결과물 생성 방법을 학습

GAN을 제안한 Ian Goodfellow가 논문에서 제시한 비유를 사용

  • 위조지폐범(생성자)과 경찰(구분자)로 나눈 후
  • 위조지폐범은 경찰을 취대한 속이려 하고, 경찰을 위조지폐를 최대한 감별하려 노력

이처럼 위조지폐범을 만들고 감별하려는 경쟁을 통해 서로의 능력이 바전하게 되고, 결국 위조지폐범은 진짜와 거의 구분할 수 없을 정도로
진짜 같은 위조지폐를 만듬

In [1]:
import tensorflow as tf
import numpy as np
In [3]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
Extracting ./mnist/data/train-images-idx3-ubyte.gz
Extracting ./mnist/data/train-labels-idx1-ubyte.gz
Extracting ./mnist/data/t10k-images-idx3-ubyte.gz
Extracting ./mnist/data/t10k-labels-idx1-ubyte.gz


setting hyper-parameter

In [4]:
total_epoch   = 100
batch_size    = 100
learning_rate = 0.0001
n_hidden      = 256
n_input       = 28*28
n_noise       = 128


  • GAN도 비지도 학습이므로 Y를 사용하지 않음
  • 구분자에 넣을 이미지가 실제 이미지와 생성한 가짜 이미지 두 개이고
  • 가짜 이미지는 노이즈에서 생성할 것이므로 노이즈를 입력할 placeholder Z를 추가
In [5]:
X = tf.placeholder(tf.float32, [None, n_input])
Z = tf.placeholder(tf.float32, [None, n_noise])


setting Generator

  • 첫 번째 가중치와 bias는 hidden layer로 출력하기 위한 변수
  • 두 번째 가중치와 bias는 export layer로 사용할 변수들
  • 두 번째 가중치의 변수 크기는 실제 이미지 크기와 같아야 함
In [6]:
with tf.name_scope("Generator_W1"):
    G_W1 = tf.Variable(tf.random_normal([n_noise, n_hidden], stddev=0.01))
    
with tf.name_scope("Generator_b1"):
    G_b1 = tf.Variable(tf.zeros([n_hidden]))
    
with tf.name_scope("Generator_W2"):
    G_W2 = tf.Variable(tf.random_normal([n_hidden, n_input], stddev=0.01))
    
with tf.name_scope("Generator_b2"):
    G_b2 = tf.Variable(tf.zeros([n_input]))


setting discriminator

  • hidden layer는 Generrator와 동일하게 구성
  • discriminator는 진짜와 얼마나 가까운지를 판단하는 값으로 0~1사이의 값을 구성
  • 출력값은 하나의 scalar

    • 실제 이미지를 판별하는 구분자 신경망과 생성한 이미지를 판별하는 구분자 신경망은 같은 변수를 사용해야함
    • 같은 신경망으로 구분을 시켜와 진짜 이미지와 가짜 이미지를 구변하는 특징들을 잡아낼 수 있기 때문
In [7]:
with tf.name_scope("discriminator_W1"):
    D_W1 = tf.Variable(tf.random_normal([n_input, n_hidden], stddev=0.01))
    
with tf.name_scope("discriminator_b1"):
    D_b1 = tf.Variable(tf.zeros([n_hidden]))
    
with tf.name_scope("discriminator_W2"):
    D_W2 = tf.Variable(tf.random_normal([n_hidden, 1], stddev=0.01))
    
with tf.name_scope("discriminator_b2"):
    D_b2 = tf.Variable(tf.zeros([1]))


setting neural network

In [8]:
def generator(noise_z):
    hidden = tf.nn.relu(tf.add(tf.matmul(noise_z, G_W1), G_b1))
    output = tf.nn.sigmoid(tf.add(tf.matmul(hidden, G_W2), G_b2))
    
    return output

def discriminator(inputs):
    hidden = tf.nn.relu(tf.add(tf.matmul(inputs, D_W1), D_b1))
    output = tf.nn.sigmoid(tf.add(tf.matmul(hidden, D_W2), D_b2))
    
    return output

def get_noise(batch_size, n_noise):
    output = np.random.normal(size=(batch_size, n_noise))
    return output


noiseZ를 이용해 가짜 이미지를 만들 생성자 G를 만들고 이 G가 만든 가짜 이미지와 진짜 이미지 X를 각각 구분자에 넣어 입력한 이미지가 진짜인지를 판별

In [9]:
G = generator(Z)
D_gene = discriminator(G)
D_real = discriminator(X)


cost

  • cost는 2개가 필요
  • 생성자가 만든 이미지를 구분자가 가짜라고 판단하도록 하는 손실값(경찰 학습용)
  • 진짜라고 판단하도록 하는 손실값(위조지폐범 학습용)

  • 경찰을 학습시키려면 진짜 이미지 판별값 D_real은 1에 가까워야 하고(진짜라고 판별)
  • 가짜 이미지 판별값 D_gene는 0에 가까워야함(가짜라고 판별)
In [10]:
with tf.name_scope("cost"):
    loss_D = tf.reduce_mean(tf.log(D_real) + tf.log(1-D_gene)) # 경찰, 높아야함
    loss_G = tf.reduce_mean(tf.log(D_gene)) # 위조지폐범, 높아야함
    
    tf.summary.scalar("loss_D", loss_D)
    tf.summary.scalar("loss_G", loss_G)


training

  • loss_D를 구할 때는 구분자 신경망에 사용되는 변수들만 사용
  • loss_G를 구할 때는 생성자 신경망에 사용되는 변수들만 사용


  • loss_D를 학습할 때는 생성자가 변하지 않고, loss_G를 학습할때는 구분자가 변하지 않기 때문
In [11]:
D_var_list = [D_W1, D_b1, D_W2, D_b2]
G_var_list = [G_W1, G_b1, G_W2, G_b2]


논문에 의하면 loss를 최대화 해야하지만, minize에 -를 붙여 최대화

In [12]:
train_D = tf.train.AdamOptimizer(learning_rate).minimize(-loss_D, var_list=D_var_list)
train_G = tf.train.AdamOptimizer(learning_rate).minimize(-loss_G, var_list=G_var_list)
In [13]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

merge = tf.summary.merge_all()
writer = tf.summary.FileWriter("./logs/mnist_gan", sess.graph)

total_batch = int(mnist.train.num_examples / batch_size)
loss_val_D, loss_val_G = 0, 0
tot_loss_val_D, tot_loss_val_G = 0, 0


  • session 설정과 minibatch를 위한 코드를 만들고 loss_D와 loss_G의 결과값을 받을 변수를 지정
  • 구분자는 X값을, 생성자는 노이즈인 Z값을 받으므로 노이즈를 생성해주는 get_noise 함수를 통해 배치 크기만큼 노이즈를 만들고 이를 입력
  • 그리고 구분자와 생성자 신경망을 학습
In [14]:
import matplotlib.pyplot as plt
plt.rcParams["axes.unicode_minus"] = False

loss_val_D_list = []
loss_val_G_list = []
In [15]:
for epoch in range(total_epoch):
    for i in range(total_batch):
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        noise = get_noise(batch_size, n_noise)
        
        _, loss_val_D = sess.run([train_D, loss_D], feed_dict={X: batch_xs, Z: noise})
        _, loss_val_G = sess.run([train_G, loss_G], feed_dict={Z: noise})
        
        tot_loss_val_D += -loss_val_D
        tot_loss_val_G += -loss_val_G
        loss_val_D_list.append(tot_loss_val_D)
        loss_val_G_list.append(tot_loss_val_G)
    
    if epoch == 0 or epoch % 20 == 19:
        print("Epoch: {}\tlossD: {:0.4f}\tlossG: {:0.4f}".format(epoch+1, 
                                                                     loss_val_D, 
                                                                     loss_val_G))
    
    if epoch ==0 or (epoch+1) % 20 == 0:
        sample_size = 10
        noise = get_noise(sample_size, n_noise)
        samples = sess.run(G, feed_dict={Z:noise})
        
        fig, ax = plt.subplots(1, sample_size, figsize=(sample_size, 1))
        
        for i in range(sample_size):
            ax[i].set_axis_off()
            ax[i].imshow(np.reshape(samples[i], (28, 28))) 
        plt.show()
        
# plt.show()        
print("\n optimization complete!")
Epoch: 1	lossD: -0.8597	lossG: -1.5412
Epoch: 20	lossD: -0.3039	lossG: -2.4034
Epoch: 40	lossD: -0.5556	lossG: -2.1424
Epoch: 60	lossD: -0.6952	lossG: -2.2227
Epoch: 80	lossD: -0.4060	lossG: -2.4146
Epoch: 100	lossD: -0.4189	lossG: -2.3728
 optimization complete!
In [16]:
_, axe = plt.subplots(1, 2, figsize=(15, 5))
axe[0].set_title("loss_D")
axe[1].set_title("loss_G")
axe[0].plot(loss_val_D_list)
axe[1].plot(loss_val_G_list)
Out[16]:
[<matplotlib.lines.Line2D at 0x7fbf43950eb8>]
In [17]:
import jptensor as jp
tf_graph = tf.get_default_graph().as_graph_def()
jp.show_graph(tf_graph)
In [18]:
from IPython.core.display import HTML, display
display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

16.RNN_word_autoComplete  (0) 2018.12.18
15.RNN_mnist  (1) 2018.12.18
13.auto-encoder  (0) 2018.12.15
12.mnist_cnn  (0) 2018.12.12
11.mnist_matplotlib_dropout_tensorgraph  (0) 2018.12.10
13.auto-encoder

auto-encoder

  • auto-encoder는 입력값과 출력값을 같게하는 신경망
  • 가운데 hidden layer가 input layer보다 작아 데이터를 압축하는 효과를 갖음
  • 이 과정으로 인해 noise 제거에 효과적
  • auto-encoder의 원리는 출력값을 입력값과 같아지도록 가중치를 찾아냄
In [1]:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt


mnist dataload

In [3]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
Extracting ./mnist/data/train-images-idx3-ubyte.gz
Extracting ./mnist/data/train-labels-idx1-ubyte.gz
Extracting ./mnist/data/t10k-images-idx3-ubyte.gz
Extracting ./mnist/data/t10k-labels-idx1-ubyte.gz


hyper parameter

In [4]:
learning_rate = 0.001 # learning_rate
training_epoch = 20 # 전체 횟수
batch_size = 256 # 한 번에 학습할 데이터(이미지 갯수)
n_hidden = 256 # hidden_layer 갯수
n_input = 28*28 # input_layer의 크기


setting place holder

In [5]:
X = tf.placeholder(tf.float32, [None, n_input], name="X")
# encoder와 decoder를 만드는 방식에 따라 다양한 auto-encoder를 맏들 수 있음


setting encoder

In [6]:
W_encode = tf.Variable(tf.random_normal([n_input, n_hidden]))
b_encode = tf.Variable(tf.random_normal([n_hidden]))

with tf.name_scope("encoder"):
    encoder = tf.add(tf.matmul(X, W_encode), b_encode)
    encoder = tf.nn.sigmoid(encoder)


setting decoder

In [7]:
W_decode = tf.Variable(tf.random_normal([n_hidden, n_input]))
b_decode = tf.Variable(tf.random_normal([n_input]))

with tf.name_scope("decoder"):
    decoder = tf.add(tf.matmul(encoder, W_decode), b_decode)
    decoder = tf.nn.sigmoid(decoder)


cost

In [8]:
# tf.pow()
# x = tf.constant([[2, 2], [3, 3]])
# y = tf.constant([[8, 16], [2, 3]])
# tf.pow(x, y)  # [[256, 65536], [9, 27]]

# 입력값인 X를 평가하기 위한 실츠값으로 사용, decoder가 내보낸 결과값의 차이를 cost로 구현
# 이 값의 차이는 거리함수로 구현
with tf.name_scope("cost"):
    cost = tf.reduce_mean(tf.pow(X-decoder, 2))
    opt = tf.train.RMSPropOptimizer(learning_rate).minimize(cost)
    
    tf.summary.scalar("cost", cost)
In [9]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
cost_epoch = []

merged = tf.summary.merge_all()
writer = tf.summary.FileWriter("./logs/mnist_autoencoder", sess.graph)

total_batch = int(mnist.train.num_examples / batch_size)

for epoch in range(training_epoch):
    total_cost = 0
    
    for i in range(total_batch):
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        _, cost_val = sess.run([opt, cost], feed_dict={X: batch_xs})
        
        total_cost += cost_val
        cost_epoch.append(total_cost)
        
        summary = sess.run(merged, feed_dict={X: batch_xs})
        writer.add_summary(summary)
    print("Epoch: %4d,  Avg.cost %.4f " % (epoch+1, total_cost/total_batch))
print("opt complete")        
Epoch:    1,  Avg.cost 0.4240 
Epoch:    2,  Avg.cost 0.1718 
Epoch:    3,  Avg.cost 0.1135 
Epoch:    4,  Avg.cost 0.1032 
Epoch:    5,  Avg.cost 0.0961 
Epoch:    6,  Avg.cost 0.0911 
Epoch:    7,  Avg.cost 0.0870 
Epoch:    8,  Avg.cost 0.0833 
Epoch:    9,  Avg.cost 0.0805 
Epoch:   10,  Avg.cost 0.0773 
Epoch:   11,  Avg.cost 0.0749 
Epoch:   12,  Avg.cost 0.0725 
Epoch:   13,  Avg.cost 0.0709 
Epoch:   14,  Avg.cost 0.0695 
Epoch:   15,  Avg.cost 0.0682 
Epoch:   16,  Avg.cost 0.0670 
Epoch:   17,  Avg.cost 0.0657 
Epoch:   18,  Avg.cost 0.0637 
Epoch:   19,  Avg.cost 0.0627 
Epoch:   20,  Avg.cost 0.0619 
opt complete
In [10]:
%matplotlib inline

plt.figure(figsize=(20, 8))
plt.plot(cost_epoch, "g")
plt.title("cost_value")
plt.show()
In [11]:
import jptensor as jp

tf_graph = tf.get_default_graph().as_graph_def()
jp.show_graph(tf_graph)
In [12]:
sample_size = 10

samples = sess.run(decoder, feed_dict={X: mnist.test.images[:sample_size]})
In [13]:
%matplotlib inline

fig, ax = plt.subplots(2, sample_size, figsize=(sample_size, 2))

for i in range(sample_size):
    ax[0][i].set_axis_off()
    ax[1][i].set_axis_off()
    ax[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))
    ax[1][i].imshow(np.reshape(samples[i], (28, 28)))
plt.show()
In [14]:
from IPython.core.display import HTML, display
display(HTML("<style> .container{width:100% !important;}</style>"))

'Deep_Learning' 카테고리의 다른 글

15.RNN_mnist  (1) 2018.12.18
14.gan  (0) 2018.12.16
12.mnist_cnn  (0) 2018.12.12
11.mnist_matplotlib_dropout_tensorgraph  (0) 2018.12.10
10.mnist_dropout  (0) 2018.12.10

+ Recent posts