{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"[Deep Learning for Computer Vision](https://pyimagesearch.com/deep-learning-computer-vision-python-book/) Practitioner Bundle 책 내용 요약\n\n![cover](https://929687.smushcdn.com/2633864/wp-content/uploads/2020/02/deeplearning-200x300-1.jpg)","metadata":{}},{"cell_type":"markdown","source":"## 10.6 Obtaining the #1 Spot on the Kaggle Leaderboard\n- transfer learning (feature extraction) 적용하면 96%도 가능\n- pre-trained ResNet50 으로 테스트 해보자","metadata":{}},{"cell_type":"markdown","source":"## Prepare other classes","metadata":{}},{"cell_type":"markdown","source":"- `HDF5DatasetWriter : hdf5 파일 저장을 위한 `h5py` wrapper","metadata":{}},{"cell_type":"code","source":"import h5py\nimport os\n\n\nclass HDF5DatasetWriter:\n    def __init__(self, dims, output_path, data_key=\"images\", buf_size=1000):\n        # check to see if the output path exists, and if so, raise an exception\n        if os.path.exists(output_path):\n            raise ValueError(\"The supplied `outputPath` already exists and cannot be overwritten.\"\n                             \"Manually delete the file before continuing.\", output_path)\n\n        # open the HDF5 database for writing and create two datasets:\n        # one to store the images/features and another to store the class labels\n        self.db = h5py.File(output_path, \"w\")\n        self.data = self.db.create_dataset(data_key, dims, dtype=\"float\")\n        self.labels = self.db.create_dataset(\"labels\", (dims[0],), dtype=\"int\")\n\n        # store the buffer size, then initialize the buffer itself along with the index into the datasets\n        self.bufSize = buf_size\n        self.buffer = {\"data\": [], \"labels\": []}\n        self.idx = 0\n\n    def add(self, rows, labels):\n        # add the rows and labels to the buffer\n        self.buffer[\"data\"].extend(rows)\n        self.buffer[\"labels\"].extend(labels)\n\n        # check to see if the buffer needs to be flushed to disk\n        if len(self.buffer[\"data\"]) >= self.bufSize:\n            self.flush()\n\n    def flush(self):\n        # write the buffers to disk then reset the buffer\n        i = self.idx + len(self.buffer[\"data\"])\n        self.data[self.idx:i] = self.buffer[\"data\"]\n        self.labels[self.idx:i] = self.buffer[\"labels\"]\n        self.idx = i\n        self.buffer = {\"data\": [], \"labels\": []}\n\n    def store_class_labels(self, class_labels):\n        # create a dataset to store the actual class label names,\n        # then store the class labels\n        dt = h5py.special_dtype(vlen=str)  # `vlen=unicode` for Py2.7\n        label_set = self.db.create_dataset(\"label_names\", (len(class_labels),), dtype=dt)\n        label_set[:] = class_labels\n\n    def close(self):\n        # check to see if there are any other entries in the buffer\n        # that need to be flushed to disk\n        if len(self.buffer[\"data\"]) > 0:\n            self.flush()\n\n        # close the dataset\n        self.db.close()","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:21:13.915849Z","iopub.execute_input":"2022-08-14T22:21:13.916736Z","iopub.status.idle":"2022-08-14T22:21:14.133630Z","shell.execute_reply.started":"2022-08-14T22:21:13.916630Z","shell.execute_reply":"2022-08-14T22:21:14.132767Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Unzip `train.zip`","metadata":{}},{"cell_type":"code","source":"import zipfile\n\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\",\"r\") as z:\n    z.extractall(\".\")","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:30:30.024688Z","iopub.execute_input":"2022-08-14T22:30:30.025213Z","iopub.status.idle":"2022-08-14T22:30:42.662741Z","shell.execute_reply.started":"2022-08-14T22:30:30.025173Z","shell.execute_reply":"2022-08-14T22:30:42.661448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## . 10.6.1 Extracting Features Using ResNet\n- `extract_features.py` 구현\n- ResNet50 이용해서 feature 뽑아서 hdf5 파일로 dataset 저장\n- ❓ 왜 만들어 둔 hdf5 파일 안 쓰지?","metadata":{}},{"cell_type":"code","source":"!pip install imutils","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:35:38.784354Z","iopub.execute_input":"2022-08-14T22:35:38.784805Z","iopub.status.idle":"2022-08-14T22:35:53.841857Z","shell.execute_reply.started":"2022-08-14T22:35:38.784771Z","shell.execute_reply":"2022-08-14T22:35:53.840269Z"},"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.applications import imagenet_utils\nfrom tensorflow.keras.preprocessing.image import img_to_array\nfrom tensorflow.keras.preprocessing.image import load_img\nfrom sklearn.preprocessing import LabelEncoder\nfrom imutils import paths\nimport numpy as np\nimport argparse\nimport random\nimport os\nfrom tqdm.notebook import tqdm","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:36:12.884989Z","iopub.execute_input":"2022-08-14T22:36:12.885485Z","iopub.status.idle":"2022-08-14T22:36:13.378408Z","shell.execute_reply.started":"2022-08-14T22:36:12.885439Z","shell.execute_reply":"2022-08-14T22:36:13.377190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prepare arguments","metadata":{}},{"cell_type":"code","source":"args = {\n    'dataset': 'train',  # path to input dataset\n    'output': 'features_using_resnet.hdf5',  # path to output HDF5 file\n    'batch_size': 16,  # batch size of images to be passed through network\n    'buffer_size': 1000,  # size of feature extraction buffer\n}","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:33:39.827856Z","iopub.execute_input":"2022-08-14T22:33:39.828300Z","iopub.status.idle":"2022-08-14T22:33:39.834758Z","shell.execute_reply.started":"2022-08-14T22:33:39.828265Z","shell.execute_reply":"2022-08-14T22:33:39.833379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# store the batch size in a convenience variable\nbs = args[\"batch_size\"]","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:33:47.884985Z","iopub.execute_input":"2022-08-14T22:33:47.885416Z","iopub.status.idle":"2022-08-14T22:33:47.890528Z","shell.execute_reply.started":"2022-08-14T22:33:47.885381Z","shell.execute_reply":"2022-08-14T22:33:47.889677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prepare dataset","metadata":{}},{"cell_type":"code","source":"# grab the list of images that we'll be describing then randomly shuffle them\n# to allow for easy training and testing splits via array slicing during training time\nprint(\"[INFO] loading images...\")\nimage_paths = list(paths.list_images(args[\"dataset\"]))\nrandom.shuffle(image_paths)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:37:42.363085Z","iopub.execute_input":"2022-08-14T22:37:42.364255Z","iopub.status.idle":"2022-08-14T22:37:42.476111Z","shell.execute_reply.started":"2022-08-14T22:37:42.364208Z","shell.execute_reply":"2022-08-14T22:37:42.474926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# extract the class labels from the image paths then encode the labels\nlabels = [p.split(os.path.sep)[-1].split(\".\")[0] for p in image_paths]\nle = LabelEncoder()\nlabels = le.fit_transform(labels)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:37:58.633299Z","iopub.execute_input":"2022-08-14T22:37:58.633765Z","iopub.status.idle":"2022-08-14T22:37:58.670276Z","shell.execute_reply.started":"2022-08-14T22:37:58.633726Z","shell.execute_reply":"2022-08-14T22:37:58.668996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prepare model","metadata":{}},{"cell_type":"code","source":"# load the ResNet50 network\nprint(\"[INFO] loading network...\")\nmodel = ResNet50(weights=\"imagenet\", include_top=False)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:38:26.641315Z","iopub.execute_input":"2022-08-14T22:38:26.641724Z","iopub.status.idle":"2022-08-14T22:38:29.657478Z","shell.execute_reply.started":"2022-08-14T22:38:26.641688Z","shell.execute_reply":"2022-08-14T22:38:29.656359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:38:35.351466Z","iopub.execute_input":"2022-08-14T22:38:35.352453Z","iopub.status.idle":"2022-08-14T22:38:35.390720Z","shell.execute_reply.started":"2022-08-14T22:38:35.352399Z","shell.execute_reply":"2022-08-14T22:38:35.389500Z"},"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.utils import plot_model\n\nplot_model(model, show_shapes=True)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:40:15.499194Z","iopub.execute_input":"2022-08-14T22:40:15.499947Z","iopub.status.idle":"2022-08-14T22:40:19.200723Z","shell.execute_reply.started":"2022-08-14T22:40:15.499906Z","shell.execute_reply":"2022-08-14T22:40:19.199526Z"},"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Extract features","metadata":{}},{"cell_type":"code","source":"# initialize the HDF5 dataset writer, then store the class label names in the dataset\ndataset = HDF5DatasetWriter((len(image_paths), 100352), args[\"output\"],\n                            data_key=\"features\", buf_size=args[\"buffer_size\"])\ndataset.store_class_labels(le.classes_)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T22:42:04.760133Z","iopub.execute_input":"2022-08-14T22:42:04.760628Z","iopub.status.idle":"2022-08-14T22:42:04.775934Z","shell.execute_reply.started":"2022-08-14T22:42:04.760587Z","shell.execute_reply":"2022-08-14T22:42:04.774479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\n# loop over the images in batches\nfor i in tqdm(np.arange(0, len(image_paths), bs), total=len(image_paths) // bs):\n    # extract the batch of images and labels,\n    # then initialize the list of actual images that will be passed through the network for feature extraction\n    batch_paths = image_paths[i:i + bs]\n    batch_labels = labels[i:i + bs]\n    batch_images = []\n\n    # loop over the images and labels in the current batch\n    for (j, image_path) in enumerate(batch_paths):\n        # load the input image using the Keras helper utility\n        # while ensuring the image is resized to 224x224 pixels\n        image = load_img(image_path, target_size=(224, 224))\n        image = img_to_array(image)\n\n        # preprocess the image by (1) expanding the dimensions and\n        # (2) subtracting the mean RGB pixel intensity from the ImageNet dataset\n        image = np.expand_dims(image, axis=0)\n        image = imagenet_utils.preprocess_input(image)\n\n        # add the image to the batch\n        batch_images.append(image)\n\n    # pass the images through the network and use the outputs as our actual features\n    batch_images = np.vstack(batch_images)\n    features = model.predict(batch_images, batch_size=bs)\n\n    # reshape the features so that each image is represented by\n    # a flattened feature vector of the `MaxPooling2D` outputs\n    features = features.reshape((features.shape[0], 100352))\n\n    # add the features and labels to our HDF5 dataset\n    dataset.add(features, batch_labels)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# close the dataset\ndataset.close()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf train","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls -al","metadata":{},"execution_count":null,"outputs":[]}]}