{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nimport os\nimport zipfile\nimport tensorflow as tf\nfrom keras.models import load_model\n\nprint(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats/train.zip\",\"r\") as z:\n    z.extractall(\".\")\n    \nwith zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats/test1.zip\",\"r\") as z:\n    z.extractall(\".\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(os.listdir('../working/train')) # os.listdir 로 working","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames = os.listdir('../working/train')\ncategories = []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(os.listdir('../working/test1')))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for filename in filenames:\n    category = filename.split('.')[0]\n    if category == 'dog':\n        categories.append(1)\n    else:\n        categories.append(0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(categories)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df1 = pd.DataFrame({\n    'name' : filenames,\n    'category' : categories\n})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df1['category'].value_counts().plot.bar()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import collections\ncollections.Counter(df1['category']) \n#각각 12500 , 12500개가 있음을 알 수 있다. ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample = random.choice(filenames)\nsample","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = load_img('../working/train/'+sample)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\n# BatchNormalization 을 통해 Vanishing 현상을 방지해준다고함. 평균과 분산을 0 , 1에 맞춰 준다고 함...  ? ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Sequential()\nmodel.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape =(128, 128, 3)))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\n# 두번재 layer 층 생성\nmodel.add(Conv2D(64, (3,3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3,3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(2, activation='softmax'))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\n# ReduceLROnPlateau 는 learning rate를 줄여주거나 높여주어 local minima 에서 빠져 나오도록 도와주는 callback함수이다. \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MODEL_DIR = './model/'\nif not os.path.exists(MODEL_DIR) :\n    os.mkdir(MODEL_DIR)\nmodelpath = './model/{epoch:02d}-{val_loss:.4f}.hdf5'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"CheckPointer = ModelCheckpoint(filepath = modelpath, moniter='val_loss', verbose1=1, save_best_only=True)\nearlystop = EarlyStopping(patience=10 )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', # 검증 accuracy를 모니터링함.\n                                            patience=2, # 2번동안 개선되지 않으면 callback을 호출한다 \n                                            verbose=1, # 과정을 보여줌\n                                            factor=0.5, # 개선이 없어 callback 호출시 학습률을 1/2 로 줄임\n                                            min_lr=0.00001) # 학습률의 하한값을 설정 ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"callbacks=[earlystop, learning_rate_reduction, CheckPointer]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df1['category'] = df1['category'].replace({0: 'cat', 1: 'dog'})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df, test_df = train_test_split(df1, test_size=0.3, random_state=30)\n \ntrain_df = train_df.reset_index(drop=True)\ntest_df = test_df.reset_index(drop=True)\n# 인덱스를 초기화 시켜준다.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(train_df['category'].value_counts())\nprint(test_df['category'].value_counts())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(train_df.shape[0])\nprint(test_df.shape[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ImageDataGenerator 를 사용하여 이미지 데이터를 부풀려준다.\n\ntrain_datagen = ImageDataGenerator(\n    rotation_range = 30, # 지정학 각도 내에서 이미지를 회전\n    rescale= 1./255, # ?? 이미지 픽셀값을 0 ~ 1 사이로 맞춰주기 위해서 1./255로 설정해주었다. \n    shear_range=0.1, # 시계 반대방향으로 밀림강도? 를 나타낸다. \n    zoom_range = 0.3, # 원본이미지를 확대/ 축소한다.\n    horizontal_flip=True, # 수평방향으로 좌우 반전 한다.\n    width_shift_range=0.1,# 수평방향 이동범위 내에서 이동시킨다.\n    height_shift_range=0.1 # 지정된 수직방향 범위 내에서 임의로 이동시킨다.  \n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 위에서 설정한 객체 train_datagen을 이용.\n# ImageDataGenerator 의 메소드 flow_from_dataframe 을 사용한다. \ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, # 사용할 데이터 프레임\n    '../working/train/',\n    x_col='name',\n    y_col='category',\n    target_size=(128, 128),\n    class_mode='categorical',\n    batch_size=15\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_datagen = ImageDataGenerator(rescale= 1./255)\ntest_generator = test_datagen.flow_from_dataframe(\n    test_df, # 사용할 데이터 프레임\n    '../working/train/', # 데이터의 위치\n    x_col='name', # 파일위치 열이름\n    y_col='category', # 클래스 열이름\n    target_size=(128, 128), # 이미지 사이즈\n    class_mode='categorical', # y값 변화방법\n    batch_size=15 # 배치 사이즈 \n)\n# flow_from_directory를 사용하여 directory를 이용하여 데이터를 생성할 수 잇다.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 시험해보기 \n# example_df = train_df.sample(n=1) # 샘플 한개를 뽑는다\nexample_df = train_df.sample(n=1).reset_index(drop=True) # 인덱스를 리셋해준다. \n\nexample_generater = train_datagen.flow_from_dataframe(\n    example_df,\n    '../working/train/', # 데이터의 위치\n    x_col='name', # 파일위치 열이름\n    y_col='category', # 클래스 열이름 여기선 dog, cat  을 저장한 열의 이름\n    target_size=(128, 128), # 이미지 사이즈\n    class_mode='categorical', # y값 변화방법\n    batch_size=8 # 배치 사이즈 \n)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# for x_batch, y_batch in example_generater:\n#     print(y_batch[0])\n# example_generater 확인결과 # 뭔가 데이터가 많이 생성됨을 알 수 있었음 . \n# x_batch , y_batch 를 돌려본결과 뭔가 임의의 데이터를 생성해 주는 것 같았음 .\n# 몇개인지는 자세히 모르겠음 . 질문해야함.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12, 12))\nfor i in range(0, 15) :\n    plt.subplot(5, 3, i+1)\n    # 서브플롯을 생성해준다. \n    for x_batch, y_batch in example_generater:\n        image = x_batch[0]\n        plt.imshow(image)\n        break\n    # 실행을 해줄때 마다 이미지 데이터가 바뀌는 걸로 보아임읠 생성된 이미지 데이터를 그려주는 듯함. \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# https://medium.com/@vijayabhaskar96/tutorial-on-keras-imagedatagenerator-with-flow-from-dataframe-8bd5776e45c1 \n# 위에 사이트를 참조한다. \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs=3 \nhistory = model.fit_generator(\n    train_generator, # 훈련데이터셋을 제공할 제네레이터를 지정합니다. train_generator \n    epochs=epochs, # 에폭스는 앞에 지정한 3을 \n    validation_data=test_generator, # 검증데이터셋을 제공할 제네레이터를 지정합니다. 앞서 지정한 test_generator를 사용하여 검증한다.\n    validation_steps=train_df.shape[0]//15, # 한 epoch 종료 시 마다 검증할 때 사용되는 검증 스텝 수를 지정합니다.\n    steps_per_epoch=test_df.shape[0]//15, # 한 epoch에 사용한 스텝 수를 지정합니다. 훈련샘플수/batch_size 로 스텝수를 지정.\n    callbacks=callbacks # 앞에서 지정한 callbacks 를 이용하여 모델에 추가.\n\n) # 제너레이터로 생성된 배치로 학습을 시키는 경우에는 fit_generator 로 학습을 시킨다. ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save(\"model.h5\")\n# 모델을 저장해준다.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_model('./model.h5') # 어제 학습시킨 모델의 가중치들을 가져온다 .","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.weights","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12))\n\n# loss[손실값], val_loss[검증손실값]을 순서대로 그려준다. \nax1.plot(history.history['loss'], color='b', label='training loss')\nax1.plot(history.history['val_loss'], color='r', label='validation loss')\n# 모델을 load 하는 과정에서 어제 그린 그래프가 사라졌다. 대충 학습이 진행될 수록 (convex) loss 값과 val_loss 값이 줄어드는 그래프가 그려짐.\nax2.set_xticks(np.arange(1, epochs, 1)) # set_xticks x축에 표시하고 싶은 값들을 설정한다. \n\nlegend = plt.legend(loc='best', shadow=True) # 구분자의 위치를 설정해준다. \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Test data를 준비해준다.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"test_filenames = os.listdir(\"../working/test1/\")\ntest_df = pd.DataFrame({\n 'filename': test_filenames\n })\nnb_samples = test_df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(len(test_df))\ntest_df['filename']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\n\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"../working/test1/\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=(128, 128),\n    batch_size=15,\n    shuffle=False\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(test_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(test_df.shape[0])\nprint(np.ceil(test_df.shape[0]/15))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predict = model.predict_generator(test_generator,\n                                  steps=np.ceil(test_df.shape[0]/15)) \n# fit_generator 와 같이 predict_generator 를 사용하여 예측해준다. ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(predict.shape)\nprint(predict[:,-1])\nnp.argmax(predict, axis=-1)\nprint(np.argmax(predict, axis=-1).shape)\nprint(test_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.argmax(predict, axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df['category'] = np.argmax(predict, axis=-1)\n# predict 값의 argmax를 이용해 0,1 인지 판단하여 test category 값에 넣어준다.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"label_map = dict((v,k) for k,v in train_generator.class_indices.items())\n# 이것도 찍어보고 이해할것 . \ntest_df['category'] = test_df['category'].replace(label_map)\n# 위에서 설정한 label_map 으로 replace 하는 것 같음. \ntest_df['category'] = test_df['category'].replace({ 'dog': 1, 'cat': 0 })\n# label_map으로 replace 한값을 다시 1 , 0 으로 replace 함","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df['category'].value_counts().plot.bar()\n# barplot을 그려서 데이터 값을 확인해 준다. ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# image와 함께 predict를 확인한다. \n\nsample_test = test_df.head(18)\nsample_test.head()\nplt.figure(figsize=(12, 24))\n\nfor index, row in sample_test.iterrows():\n    filename = row['filename']\n    category = row['category']\n    img = load_img(\"../working/test1/\"+filename, target_size=(128, 128))\n    plt.subplot(6, 3, index+1)\n    plt.imshow(img)\n    plt.xlabel(filename + '(' + \"{}\".format(category) + ')' )\nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 제출한다. \n\nsubmission_df = test_df.copy()\nsubmission_df['id'] = submission_df['filename'].str.split('.').str[0]\nsubmission_df['label'] = submission_df['category']\nsubmission_df.drop(['filename', 'category'], axis=1, inplace=True)\nsubmission_df.to_csv('submission.csv', index=False)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history.history","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}