{"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":"# 预训练——数据增强的特征提取\n- 直接在卷积基后面上重新定义全连接层，然后进行训练\n- 这种方式更加简单一点，而且可以使用数据增强技术","metadata":{}},{"cell_type":"code","source":"#  解压文件\n# kaggle会将文件解压到根目录下的working路径下\nimport zipfile\nwith zipfile.ZipFile('../input/dogs-vs-cats/train.zip', 'r') as z:\n    z.extractall('.')\nwith zipfile.ZipFile('../input/dogs-vs-cats/test1.zip', 'r') as z:\n    z.extractall('.')","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:12:17.1618Z","iopub.execute_input":"2022-04-14T13:12:17.162058Z","iopub.status.idle":"2022-04-14T13:12:33.98616Z","shell.execute_reply.started":"2022-04-14T13:12:17.161985Z","shell.execute_reply":"2022-04-14T13:12:33.985348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 准备数据集，将原来比较大的数据集进行抽样，形成一个比较小的数据集\nimport os, shutil\noriginal_dataset_dir = '../working/train'\nbase_dir = '../working/cats_and_dogs_small'\nos.mkdir(base_dir)\ntrain_dir = os.path.join(base_dir, 'train')\nvalid_dir = os.path.join(base_dir, 'valid')\ntest_dir = os.path.join(base_dir, 'test')\nos.mkdir(train_dir)\nos.mkdir(valid_dir)\nos.mkdir(test_dir)\n\ntrain_dir_dogs = os.path.join(train_dir, 'dogs')\nvalid_dir_dogs = os.path.join(valid_dir, 'dogs')\ntest_dir_dogs = os.path.join(test_dir, 'dogs')\ntrain_dir_cats = os.path.join(train_dir, 'cats')\nvalid_dir_cats = os.path.join(valid_dir, 'cats')\ntest_dir_cats = os.path.join(test_dir, 'cats')\nos.mkdir(train_dir_cats)\nos.mkdir(valid_dir_cats)\nos.mkdir(test_dir_cats)\nos.mkdir(train_dir_dogs)\nos.mkdir(valid_dir_dogs)\nos.mkdir(test_dir_dogs)\n\n# Copy first 1000 cat images to train_cats\nfnames = ['cat.{}.jpg'.format(i) for i in range(1000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(train_dir_cats, fname)\n    shutil.copyfile(src, dst)\n# Copy next 500 cat images to valid_cats\nfnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(valid_dir_cats, fname)\n    shutil.copyfile(src, dst)\n# Copy next 500 cat images to test_cats\nfnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(test_dir_cats, fname)\n    shutil.copyfile(src, dst)\n# Copy first 1000 dog images to train_dogs\nfnames = ['dog.{}.jpg'.format(i) for i in range(1000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(train_dir_dogs, fname)\n    shutil.copyfile(src, dst)\n# Copy next 500 dog images to valid_dogs\nfnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(valid_dir_dogs, fname)\n    shutil.copyfile(src, dst)\n# Copy next 500 dog images to test_dogs\nfnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(test_dir_dogs, fname)\n    shutil.copyfile(src, dst)","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:12:33.989915Z","iopub.execute_input":"2022-04-14T13:12:33.990179Z","iopub.status.idle":"2022-04-14T13:12:34.38552Z","shell.execute_reply.started":"2022-04-14T13:12:33.990139Z","shell.execute_reply":"2022-04-14T13:12:34.384779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 定义卷积基\nfrom keras.applications import vgg16\nconv_base = vgg16.VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:12:34.390602Z","iopub.execute_input":"2022-04-14T13:12:34.39108Z","iopub.status.idle":"2022-04-14T13:12:42.275737Z","shell.execute_reply.started":"2022-04-14T13:12:34.391043Z","shell.execute_reply":"2022-04-14T13:12:42.274912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 使用卷积基，然后加上全连接层\nfrom keras import models, layers\nmodel = models.Sequential()\nmodel.add(conv_base)\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(256, activation='relu'))\nmodel.add(layers.Dense(1, activation='sigmoid'))\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:12:42.278749Z","iopub.execute_input":"2022-04-14T13:12:42.278944Z","iopub.status.idle":"2022-04-14T13:12:42.35687Z","shell.execute_reply.started":"2022-04-14T13:12:42.278919Z","shell.execute_reply":"2022-04-14T13:12:42.356037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 将卷积基的参数设置为不可训练\nprint(f'冻结之前，模型参数的数量为：{len(model.trainable_weights)}')\nconv_base.trainable = False\nprint(f'冻结之后，模型参数的数量为：{len(model.trainable_weights)}')","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:12:42.3584Z","iopub.execute_input":"2022-04-14T13:12:42.358923Z","iopub.status.idle":"2022-04-14T13:12:42.366398Z","shell.execute_reply.started":"2022-04-14T13:12:42.35887Z","shell.execute_reply":"2022-04-14T13:12:42.365544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 开始准备数据、训练模型\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers\ntrain_datagen = ImageDataGenerator(rescale=1./255,rotation_range=40,\n                                      width_shift_range=0.2,height_shift_range=0.2,\n                                        shear_range=0.2,zoom_range=0.2,horizontal_flip=True,\n                                        fill_mode='nearest')\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntrain_generator = train_datagen.flow_from_directory(train_dir,target_size=(150,150),batch_size=20,class_mode='binary')\nvalid_generator = test_datagen.flow_from_directory(valid_dir,target_size=(150,150),batch_size=20,class_mode='binary')\nmodel.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['acc'])\nhistory = model.fit_generator(train_generator,steps_per_epoch=100,epochs=30,validation_data=valid_generator,validation_steps=50)","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:12:42.367851Z","iopub.execute_input":"2022-04-14T13:12:42.368488Z","iopub.status.idle":"2022-04-14T13:21:47.029544Z","shell.execute_reply.started":"2022-04-14T13:12:42.368431Z","shell.execute_reply":"2022-04-14T13:21:47.028756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nacc = history.history['acc']\nval_acc = history.history['val_acc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs = range(1, len(acc) + 1)\n\nplt.plot(epochs, acc, 'bo', label='Training acc')\nplt.plot(epochs, val_acc, 'b', label='Validation acc')\nplt.title('Training and validation accuracy')\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:21:47.031039Z","iopub.execute_input":"2022-04-14T13:21:47.031801Z","iopub.status.idle":"2022-04-14T13:21:47.420957Z","shell.execute_reply.started":"2022-04-14T13:21:47.031762Z","shell.execute_reply":"2022-04-14T13:21:47.420247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history.history","metadata":{"execution":{"iopub.status.busy":"2022-04-14T13:26:32.688013Z","iopub.execute_input":"2022-04-14T13:26:32.688305Z","iopub.status.idle":"2022-04-14T13:26:32.695548Z","shell.execute_reply.started":"2022-04-14T13:26:32.688275Z","shell.execute_reply":"2022-04-14T13:26:32.694868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}