{"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":"# 사진들이 zip 파일에 묶여있다 -> 압축을 풀어줘야함\n!unzip /kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!unzip /kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#python imange library\nfrom PIL import Image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 사진확인\nImage.open(\"train/cat.2.jpg\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import glob\nglob.glob(\"train/*\") #jpg 뿐만 아니라 다른 확장명 파일이 있으면 *.jpg 사용","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 모델링 하기전에 최소 전처리\n# 1. dataframe 만들기 (column1: 이미지 경로/주소, column2: 정답값)\n\ntrain = pd.DataFrame({\"path\": glob.glob(\"train/*\")})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train[\"path\"].apply(lambda x: x.split(\"/\") )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train[\"path\"].apply(lambda x: x.split(\"/\")[1].split(\".\")[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train[\"target\"] = train[\"path\"].apply(lambda x: x.split(\"/\")[1].split(\".\")[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nx_train,x_valid = train_test_split(train,test_size=0.2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # 모델링 하기전에 최소 전처리\n# # 2. 특정 라이브러리를 가져오기\n\n# from keras.preprocessing.image import ImageDataGenerator\n# idg = ImageDataGenerator()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n#augmentation(이미지 증식) => 데이터 수 모자를 때\n#데이터가 추가되는건 아니고 학습을 때 random 50%확률로 augmentation이 적용이 됨\n#원본 데이터가 학습이 안될 수도 있음 => epochs을 늘려줘야함\nidg = ImageDataGenerator(horizontal_flip=True)\ntrain_generator = idg.flow_from_dataframe(x_train, x_col = \"path\", y_col = \"target\", target_size = (300,300), batch_size = 32)\nvalid_generator = idg.flow_from_dataframe(x_valid, x_col = \"path\", y_col = \"target\", target_size = (300,300), batch_size = 32)\n#image 커지면 (300,300) out of memory error -> batch size 32 (줄여줌)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # 이미지의 사이즈가 다 다름 => 차원이 다름 => 맞춰줘야함\n# # 25000개 이미지 => 용량 소모량이 큼 => 학습할 때 데이터를 한번에 가져오지 않고 batch size라는 개념으로 일부분씩 가져옴 (100개씩 끊어서 가져오기)\n# # ImageDataGenerator에 option을 넣어준다.\n\n# train_generator = idg.flow_from_dataframe(train, x_col = \"path\", y_col = \"target\", target_size = (200,200), batch_size = 100)\n# #option 확인: train, 옆에 커서두고 shift + tab 5번\n# #target_size: 이미지 마다 size가 다름, 다르면 데이터의 차원이 달라서 학습이 안됨 => size 맞춰줌, rescale","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 모델 성능 올리기! 점수 올리는 방법\n* 이미지 사이즈 늘리기 (300,300)까지\n* layer 추가\n* 학습량 늘리기\n* 모델을 가져오기\n    * 구조가 효율적이기 때문에 점수가 잘나옴\n    * 다른곳에서 모델을 가져와서 쓰는것이 압도적으로 점수가 잘나옴"},{"metadata":{"trusted":true},"cell_type":"code","source":"# 모델링\nfrom keras import Sequential #순서대로, 층 쌓기\nfrom keras.layers import *\n\n#이미 만들어진 모델 (보통 가장 최신 모델) 가져와서 적용하기 -> 점수 상승\n# from keras.applications.inception_v3 import InceptionV3","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"! pip install -U git+https://github.com/qubvel/efficientnet","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from efficientnet.tfkeras import EfficientNetB1\nfrom keras.optimizers import SGD\n\nmodel = Sequential()\nmodel.add(EfficientNetB1(weights=\"imagenet\",include_top=False,pooling=\"avg\"))\nmodel.add(Dense(2,activation=\"softmax\"))\nmodel.compile(metrics=[\"acc\"], loss=\"categorical_crossentropy\", optimizer=SGD(lr=0.01,nesterov=True,momentum=0.9))\n#기본적으로 adam optimizer가 잘나옴\n#여기는 SGD가 더 잘나옴\n#해보면서 찾아야함\n#SGD option: learning rate, \n#nesterov=True(항상 True로 주는게 좋음): 등고선 내려올 때 특정 시점에서 어떤 방향으로 가는게 최적인가? 내려온 방향을 고려해서\n#예전 벡터와 지금 설정하는 벡터의 합을 해서 설정하겠다 (예전 백터 고려하는게 좋음)\n#nesterov 예전 내용 유지 할꺼냐, momentum은 얼마나 유지할꺼냐 (보통 0.9/0.95)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# #InceptionV3 모델 사용\n# model = Sequential()\n# model.add(InceptionV3(weights=\"imagenet\",include_top=False,pooling=\"avg\")) #InceptionV3 안에는 많은 여러가지 layer가 들어있음\n# #weights(가중치): 처음에 W는 랜덤 값(i.e.정확도가 50%에서 차근차근 좋아짐), 가중치를 imagenet에서 가져옴\n# #imagenet: 수백만장의 이미지가 있는 곳에서 여러 클래스 별로 학습을 시켜놓은 것? 특정 케이스를 제외하고는 모델 점수가 항상 좋음\n# #1.고양이나 강아지가 이미 imagenet에서 클래스로 들어있을 수도 있음(이미 특징 분류,학습완료)\n# #2.기본적으로 사진들에는 공통적인 부분이 있음(직선정보, 곡선, 명암, 색채감), 일반적인 사진들은 배경정보가 있으므로 배경정보를 무시할 수 있음-> 특정 물체에 집중할 수 있다\n# # => 전이학습(transfer 학습)\n# #include_top:딥러닝 층을 보면 맨 아래있는 층이 입력층, 맨 위에있는 층이 출력층\n# #출력층을 포함하지 않고 가져오겠다.(천개의 클래스를 나누는 dense layer를 가져올 필요가 없음)\n# #pooling:원래는 중간에 차원축소를 위해 Flatten(지역/위치정보 날라감)를 넣는데 그 대신 global average pooling(localizaion 정보 저장가능)를 사용\n# #pooling은 avg/max가 있음\n# model.add(Dense(2,activation=\"softmax\"))\n# model.compile(metrics=[\"acc\"], loss=\"categorical_crossentropy\",optimizer=\"adam\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# model = Sequential() #모델 선언 시작\n# #층 최소 2개: 입력층, 출력층\n# #CNN층\n# model.add(Conv2D(32,(3,3),activation='relu',input_shape=(100,100,3))) #입력층은 convolution layer, 2차원\n# # 1번 option: 몇개 특징을 추출할 껀지 option, 보통 2의 거듭제곱\n# # 2번 option (filter size): (3,3) 박스가 사진을 돌면서 이미지 확인, 보통 (3,3)이 제일 효율적(속도, 점수)\n# # 3번 option: 비선형성을 학습할 수 있는 활성화 함수, 기본적으로 relu를 가장 많이 씀\n# # 100,100,3 : rgb channel\n\n# #Conv layer와 Dense layer(1차원)의 차원이 다르기 때문에 Conv를 펼쳐줘야함\n# model.add(Flatten())\n\n# model.add(Dense(2,activation = \"softmax\")) #출력층은 Dense layer(정답클래스의 갯수,activation)\n# # 학습할때 Dense layer 또한 활성화 함수는 항상 relu\n# # 출력층은 0과1 사이의 확률값으로 바뀌어야되기 때문에 softmax 씀 (다중분류문제)\n\n# model.summary() #모델 구조 확인\n# #(100,100)이 (3,3) Conv layer가 지나가면서 이미지 끝부분까지 (3,3)이 갈 수 없기 때문에 \n# #32장의 사진모임이 추출\n# #Conv layer는 3차원 Dense layer는 1차원\n# #None은 데이터 갯수\n\n\n# model.compile(metrics=[\"acc\"], loss=\"categorical_crossentropy\",optimizer=\"adam\") #optimizer, metrics, loss\n#loss값 categorical crossentropy 고정: 여러가지 사진을 분류할 때 (다중분류 multiclassification 문제)\n#log loss와 똑같은 값\n#loss(손실함수): y=wx+b (x=input) 어떤 이미지가 들어가더라도 y를 맞추는 w값을 찾는것이 딥러닝의 목표\n#모델이 학습을 하면서 w값이 업데이트 되는데 이 때 w가 loss(손실함수)를 보면서 업데이트\n#=모델이 어떤 방향으로 학습해 나갈 것인가?\n\n#데이터의 복잡도에 따라 optimizer 선택","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\n\nes = EarlyStopping(patience=5) #epochs, overfitting 방지\n\n#patience 값 때문에 10번이 최적이어도 13번 돌림 (3번 참기) => 결국 overfitting\n#modelcheckpoint 사용해서 최적의 포인트 저장\n#10번째 가중치를 가져와서 모델 만들 수 있음\nmc = ModelCheckpoint(\"best.h5\",save_best_only = True) #어디에 저장, 최고만 저장 (메모리 비효율적 사용 방지)\n#.h5는 확장자 => 가중치 저장 가능 \n\n#reduce learning rate\n#어느순간부터 점수가 안나올 때 \n#딥러닝의 목표는 global minimum (local minimum x)\n#learning rate가 크면 global minimum으로 못가고 그 주위를 맴돌 수 있음 (learning rate가 너무 클 때)\n#local minimum이 많으면 관성에 의해서 갇혀서?? 최적의 지점까지 못감 (learning rate가 너무 작을 때)\nrp = ReduceLROnPlateau(patience=3, factor=0.2) #es에 들어가는 patience 보다 작아야함\n#rp가 patience가 더 커버리면 es 되기 전에 rp가 줄어들었어야 했는데 못 줄이고 학습이 끝남(멈춤 by es)\n#factor 0.1 default => learning rate 몇 줄일꺼냐","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#학습\nmodel.fit(train_generator, validation_data = valid_generator, epochs=3, callbacks=[es,mc,rp]) #정답값을 따로 넣지 않아도됨, 이미 train_generator 만들 때 y 값 들어가 있음","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_weights(\"best.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test = pd.DataFrame({\"path\": glob.glob(\"test/*\")})\ntest","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_generator = idg.flow_from_dataframe(test, \n                                         x_col = \"path\", \n                                         y_col = None, \n                                         target_size = (300,300), \n                                         batch_size = 32, \n                                         class_mode = None, #기본값:categorical \n                                         #test set은 y값이 없기 때문에 class_mode를 None으로 설정\n                                         shuffle = False #기본값:True\n                                         #제출할 때 우리가 원하는 데이터 순서에 맞게 정답값을 제출 해야되기 떄문에 예측 할 때는 셔플 빼주기\n                                        )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#예측\nresult = model.predict(test_generator, verbose = 1)\n#언제 끝날지 알기위해 verbose를 1로 넣어줌","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub = pd.read_csv(\"/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv\")\nsub","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"result","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator.class_indices","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* 평가지표 log loss임\n* 모델이 값이 쏠려있는 경우가 있음 (0.99999 등) -> 특정 데이터에 대해 강아지 고양이로 확신하고 있음\n* -> log loss에서는 치명적\n* y값에 0이나 1이 들어가면 log loss 값이 확 => 큰 손해\n<br>\n=> post processing: 대회에서는 평가지표에 따라 정답값을 수정하기도 함"},{"metadata":{"trusted":true},"cell_type":"code","source":"sub[\"label\"] = result[:,1].clip(0.005,0.995) #강아지일 확률 제출\n#0.005보다 작으면 0.005로 바꿈\n#0.995보다 크면 0.995로 바꿈\nsub ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test #순서가 다름","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub[\"id\"] = test[\"path\"].apply(lambda x: x.split(\"/\")[1].split(\".\")[0])\nsub #sub의 id를 test set순서로 맞춰주기","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.to_csv(\"sub.csv\",index=0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 점수 올리기\n# 앙상블 기법 사용\n* 가중치 줘서 합치기\n* 두개의 branch로 나눠서?"}],"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}