{"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":"code","source":"import os  # 文件/目录方模块\nimport cv2  # OpenCV模块\nimport random  # 随机模块\nimport numpy as np  # 数值计算模块\nimport pandas as pd  # 结构化数据分析模块\nimport seaborn as sns  # 统计绘图模块\nimport matplotlib.pyplot as plt  # 绘图模块\nimport zipfile  # zip文件处理模块\nfrom sklearn.model_selection import train_test_split  # 样本分割模块\nfrom sklearn.metrics import classification_report  # 分类评价模块\nfrom tqdm import tqdm  # 进度条模块\nfrom random import shuffle # 混洗模块\nfrom IPython.display import SVG\nfrom keras.utils.vis_utils import model_to_dot\nfrom keras.utils import plot_model\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.optimizers import RMSprop\n%matplotlib inline ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 227\nSAMPlE_ZIP_FILE = '/kaggle/input/dogs-vs-cats/train.zip'\nNUM_CLASSES = 2\nEPOCHS = 30\nBATCH_SIZE = 128\nSAMPLE_PATH = '/kaggle/working/train/'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_zipfile = zipfile.ZipFile(SAMPlE_ZIP_FILE, 'r')    # 打开压缩包\nsample_image_file_list = sample_zipfile.namelist()        # 或缺压缩包的文件名称列表，包括目录名称\nsample_image_file_list.pop(0)                             # 删除目录名称，仅保留图像文件名称\nprint('样本图像文件总数：', len(sample_image_file_list))     # 输出样本总数量\ndata = sample_zipfile.read(sample_image_file_list[0])     # 将第一个图像样本文件内容读入内存缓冲区\nimage = cv2.imdecode(np.frombuffer(data, np.uint8), 1)    # 解码为OpenCV的BGR格式，1表示彩色图像\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)            # 转化为RGB格式\nplt.imshow(image)                                         # 绘制输出图像样本","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', \"r\") as z:\n    z.extractall(\".\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_image_file_list = os.listdir(SAMPLE_PATH)\ncategories = []\nfor filename in sample_image_file_list:\n    category = filename.split(\".\")[0]\n    if category == \"dog\":\n        categories.append(\"dog\")\n    else:\n        categories.append(\"cat\")\ndf = pd.DataFrame({\n    \"filename\" : sample_image_file_list,\n    \"category\" : categories\n})","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head(10)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.category.value_counts().plot.bar()\ncats = len(df[df['category'] == 'cat'])\ndogs = len(df[df['category'] == 'dog'])\nplt.title(str(cats)+\" cats\" + \" | \" +str(dogs)+\" dogs\")\nplt.ylabel(len(df))\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.tail(10)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size = 0.2, random_state = 42)\ntrain_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 数据增强\ntrain_datagen = ImageDataGenerator(rotation_range=20,\n                                   rescale=1./255,\n                                   shear_range=0.15,\n                                   zoom_range=0.15,\n                                   horizontal_flip=True,\n                                   width_shift_range=0.2,\n                                   height_shift_range=0.2,\n                                   fill_mode=\"nearest\")\n\n# 数据集生成器\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    SAMPLE_PATH, \n    x_col='filename',\n    y_col='category',\n    target_size=(IMG_SIZE,IMG_SIZE),  # (227, 227)\n    class_mode='binary',\n    batch_size=BATCH_SIZE,\n    color_mode=\"rgb\",\n    shuffle=True\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_datagen = ImageDataGenerator(rescale=1./255)\n\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    SAMPLE_PATH, \n    x_col='filename',\n    y_col='category',\n    target_size=(IMG_SIZE,IMG_SIZE),  # (227, 227)\n    class_mode='binary',\n    batch_size=BATCH_SIZE,\n    color_mode=\"rgb\",\n    shuffle=True\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 导入必须的包\nimport tensorflow as tf\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input\nfrom tensorflow.keras.layers import Conv2D\nfrom tensorflow.keras.layers import MaxPooling2D\nfrom tensorflow.keras.layers import Activation\nfrom tensorflow.keras.layers import Flatten\nfrom tensorflow.keras.layers import Dropout\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras.layers import BatchNormalization\n\n\n# 定义AlexNet类\nclass AlexNet:\n    @staticmethod\n    def build(height, width, channel):\n        \"\"\"\n        根据输入样本的维度（width、height、channel），分类数量创建AlexNet网络模型\n        Args:\n            height:  输入样本的高度\n            width:   输入样本的宽度\n            channel: 输入样本的通道\n        Returns:\n            AlexNet网络模型对象\n\n        \"\"\"\n\n        # 输入形状\n        shape = (height, width, channel)\n        inputs = Input(shape, name=\"input\")\n        # 第一层: CONV => RELU => LRN => POOL\n        x = Conv2D(filters=96,\n                   kernel_size=(11, 11),\n                   strides=(4, 4),\n                   input_shape=shape,\n                   padding=\"valid\",\n                   name=\"conv_1\")(inputs)\n        # 局部响应标准化\n        x = tf.nn.local_response_normalization(x, depth_radius=5, bias=2, alpha=0.0001, beta=0.75)\n        x = Activation(\"relu\", name=\"relu_1\")(x)\n        x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name=\"max_pooling_1\")(x)\n\n        # 第二层: CONV => RELU => LRN => POOL\n        x = Conv2D(filters=256,\n                   kernel_size=(5, 5),\n                   padding=\"same\",\n                   name=\"conv_2\")(x)\n        # 局部响应标准化\n        x = tf.nn.local_response_normalization(x, depth_radius=5, bias=2, alpha=0.0001, beta=0.75)\n        x = Activation(\"relu\", name=\"relu_2\")(x)\n        x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name=\"max_pooling_2\")(x)\n\n        # 第三层: CONV => RELU\n        x = Conv2D(filters=384,\n                   kernel_size=(3, 3),\n                   padding=\"same\",\n                   name=\"conv_3\")(x)\n        x = Activation(\"relu\", name=\"relu_3\")(x)\n\n        # 第四层: CONV => RELU\n        x = Conv2D(filters=384,\n                   kernel_size=(3, 3),\n                   padding=\"same\",\n                   name=\"conv_4\")(x)\n        x = Activation(\"relu\", name=\"relu_4\")(x)\n\n        # 第五层: CONV => RELU => POOL\n        x = Conv2D(filters=256,\n                   kernel_size=(3, 3),\n                   padding=\"same\",\n                   name=\"conv_5\")(x)\n        x = Activation(\"relu\", name=\"relu_5\")(x)\n        x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name=\"max_pooling_3\")(x)\n\n        # 第六层: FLATTEN => DENSE => RELU => 随机失活\n        x = Flatten()(x)\n        x = Dense(4096, name=\"fully_connect_1\")(x)\n        x = Activation(\"relu\", name=\"relu_6\")(x)\n        x = Dropout(0.5, name=\"drop_1\")(x)\n\n        # 第七层: DENSE => RELU => 随机失活\n        x = Dense(4096, name=\"fully_connect_2\")(x)\n        x = Activation(\"relu\", name=\"relu_7\")(x)\n        x = Dropout(0.5, name=\"drop_2\")(x)\n\n        # 第八层 DENSE => SOFTMAX\n        x = Dense(1, name=\"fully_connect_3\")(x)\n        outputs = Activation(\"sigmoid\", name=\"sigmoid\")(x)\n\n        return Model(inputs, outputs)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.optimizers import SGD\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nimport json\n\nmodel = AlexNet.build(IMG_SIZE, IMG_SIZE, 3)\nopt = SGD(learning_rate=0.01, momentum=0.9, decay=0.005)\nmodel.compile(optimizer=opt, loss='binary_crossentropy', metrics = ['accuracy'])\n\n# 校验损失不下降时降低学习速率\nlr_reducer = ReduceLROnPlateau(monitor='val_loss', \n                               factor=0.1, \n                               patience=3, \n                               min_lr=0.0001, \n                               cooldown=1,\n                               verbose=1)\nhistory = model.fit(\n    train_generator,\n    steps_per_epoch=len(train_df)/BATCH_SIZE,\n    epochs=30,\n    validation_data=validation_generator,\n    validation_steps=len(validate_df)/BATCH_SIZE,\n    callbacks=[lr_reducer]\n)\n\n# 将训练得到的模型保存到文件\nprint(\"[信息] 保存模型...\")\nMODEL_FILE = 'AlexNet.h5'\nmodel.save(MODEL_FILE, overwrite=True)\n\n# 保存训练历史数据\njson_path = \"AlexNet_Dogs_vs_Cat_Training_History.json\"\nf = open(json_path, \"w\")\nf.write(json.dumps(str(history.history), skipkeys=True))\nf.close()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n\nfigure, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\nt = figure.suptitle('AlexNet Training Performance', fontsize=12)\nfigure.subplots_adjust(top=0.85, wspace=0.3)\n\nepoch_list = list(range(1, EPOCHS + 1))\nax1.plot(epoch_list, history.history['accuracy'], label='Train Accuracy')\nax1.plot(epoch_list, history.history['val_accuracy'], label='Validation Accuracy')\nax1.set_xticks(np.arange(0, EPOCHS + 1, 5))\nax1.set_ylabel('Accuracy Value')\nax1.set_xlabel('Epoch #')\nax1.set_title('Accuracy')\nl1 = ax1.legend(loc=\"best\")\n\nax2.plot(epoch_list, history.history['loss'], label='Train Loss')\nax2.plot(epoch_list, history.history['val_loss'], label='Validation Loss')\nax2.set_xticks(np.arange(0, EPOCHS + 1, 5))\nax2.set_ylabel('Loss Value')\nax2.set_xlabel('Epoch #')\nax2.set_title('Loss')\nl2 = ax2.legend(loc=\"best\")\n\nGRAPH_FILE = 'AlexNet_Training_Performance.pdf'\nfigure.savefig(GRAPH_FILE)\nfigure.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}