{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"},{"sourceId":30378,"sourceType":"datasetVersion","datasetId":23777}],"dockerImageVersionId":29662,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## 使用CNN 网络区分狗和猫的图像","metadata":{"editable":false}},{"cell_type":"code","source":"# 导入必要的库\nimport numpy as np \nimport pandas as pd \nimport matplotlib.pyplot as plt\nfrom glob import glob\nimport tensorflow as tf\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.utils import to_categorical\nfrom keras.models import Sequential, load_model, Model\nfrom keras.layers import Conv2D, MaxPooling2D, BatchNormalization, Dropout\nfrom keras.layers import Dense, Flatten\nfrom keras.callbacks import EarlyStopping\nimport cv2\nimport os","metadata":{"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#设置超参数、数据集路径如下：\ncategory = [\"cats\", \"dogs\"]\n\nEPOCHS                  = 10\nIMGSIZE                 = 128\nCHANNELS                = 1 # grayscale\nBATCH_SIZE              = 32\nSTOPPING_PATIENCE       = 8\nVERBOSE                 = 1\nMODEL_NAME              = 'cnn_50epoch_imgsize128.h5'\nOPTIMIZER               = 'adam'\nTRAINING_DIR            = '../input/cat-and-dog/training_set/training_set'\nTEST_DIR                = '../input/cat-and-dog/test_set/test_set'","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:22:18.88086Z","iopub.execute_input":"2025-06-03T14:22:18.881139Z","iopub.status.idle":"2025-06-03T14:22:18.885444Z","shell.execute_reply.started":"2025-06-03T14:22:18.8811Z","shell.execute_reply":"2025-06-03T14:22:18.884581Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 读取和准备数据集","metadata":{"editable":false}},{"cell_type":"code","source":"generator = ImageDataGenerator(rescale=1./255, \n                               shear_range=0.15, \n                               zoom_range=0.2, \n                               horizontal_flip=True\n                              ) \n\ntrain_data = generator.flow_from_directory( directory=TRAINING_DIR, \n                                            target_size=(IMGSIZE, IMGSIZE),\n                                            color_mode='grayscale',\n                                            classes=category, \n                                            batch_size=BATCH_SIZE, \n                                            )\n\n\ntest_data = generator.flow_from_directory( directory=TEST_DIR, \n                                           target_size=(IMGSIZE, IMGSIZE), \n                                           color_mode='grayscale',\n                                           classes=category, \n                                           batch_size=BATCH_SIZE,\n                                           shuffle=False\n                                           )","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:22:58.116313Z","iopub.execute_input":"2025-06-03T14:22:58.116583Z","iopub.status.idle":"2025-06-03T14:25:43.657651Z","shell.execute_reply.started":"2025-06-03T14:22:58.116531Z","shell.execute_reply":"2025-06-03T14:25:43.656948Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 构建CNN模型并打印出模型的结构","metadata":{"editable":false}},{"cell_type":"code","source":"model = Sequential()\n\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMGSIZE, IMGSIZE, CHANNELS)))\nmodel.add(Conv2D(32, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(BatchNormalization())\n\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(BatchNormalization())\n\nmodel.add(Flatten())\nmodel.add(Dropout(0.25))\n\nmodel.add(Dense(2, activation='softmax'))\n\nmodel.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:26:15.603271Z","iopub.execute_input":"2025-06-03T14:26:15.603593Z","iopub.status.idle":"2025-06-03T14:26:15.86366Z","shell.execute_reply.started":"2025-06-03T14:26:15.603538Z","shell.execute_reply":"2025-06-03T14:26:15.86293Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 训练模型","metadata":{"editable":false}},{"cell_type":"code","source":"es = EarlyStopping(patience=STOPPING_PATIENCE, \n                   monitor='val_accuracy', \n                   mode='max', \n                   verbose=1, \n                   restore_best_weights=True)\n\nhistory = model.fit_generator(train_data, \n                              epochs=EPOCHS, \n                              validation_data=test_data,\n                              shuffle=True,\n                              callbacks=[es]\n                             )","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-06-03T14:26:19.31314Z","iopub.execute_input":"2025-06-03T14:26:19.313412Z","iopub.status.idle":"2025-06-03T14:33:37.845334Z","shell.execute_reply.started":"2025-06-03T14:26:19.313373Z","shell.execute_reply":"2025-06-03T14:33:37.844609Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 检验模型的效果","metadata":{"editable":false}},{"cell_type":"code","source":"train_acc = model.evaluate(train_data)\ntest_acc = model.evaluate(test_data)","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-06-03T14:34:38.170949Z","iopub.execute_input":"2025-06-03T14:34:38.171232Z","iopub.status.idle":"2025-06-03T14:35:21.938711Z","shell.execute_reply.started":"2025-06-03T14:34:38.171193Z","shell.execute_reply":"2025-06-03T14:35:21.937925Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 对模型效果做可视化分析","metadata":{"editable":false}},{"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(18, 10))\nax1.plot(history.history['loss'], color='b', label=\"Training loss : {:0.4f}\".format(train_acc[0]))\nax1.plot(history.history['val_loss'], color='r', label=\"validation loss : {:0.4f}\".format(test_acc[0]))\nax1.legend()\n\nax2.plot(history.history['accuracy'], color='b', label=\"Training accuracy : {0:.4f}\".format(train_acc[1]))\nax2.plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy : {0:.4f}\".format(test_acc[1]))\n\nlegend = plt.legend(loc='best', shadow=True)\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:35:24.077023Z","iopub.execute_input":"2025-06-03T14:35:24.077275Z","iopub.status.idle":"2025-06-03T14:35:24.49563Z","shell.execute_reply.started":"2025-06-03T14:35:24.077238Z","shell.execute_reply":"2025-06-03T14:35:24.494858Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 查看具体的图片和对应的分类","metadata":{"editable":false}},{"cell_type":"code","source":"test_paths = np.array(glob(TEST_DIR + '/*/*.jpg'))\nnp.random.seed(42)\nids = np.random.choice(np.arange(len(test_paths)), size=32)\nsamples = test_paths[ids]","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:35:29.91142Z","iopub.execute_input":"2025-06-03T14:35:29.911675Z","iopub.status.idle":"2025-06-03T14:35:29.942027Z","shell.execute_reply.started":"2025-06-03T14:35:29.911638Z","shell.execute_reply":"2025-06-03T14:35:29.94133Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"code","source":"im_test = []\nc = 0\nfor img in samples:\n    c = c + 1\n    img_path =img\n    img_arr = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)\n    img_arr = cv2.resize(img_arr, (IMGSIZE, IMGSIZE))\n    img_arr = img_arr / 255.0\n    im_test.append(img_arr)\n\n    \nim_test = np.array(im_test).reshape(-1, IMGSIZE, IMGSIZE, 1)\nim_pred = model.predict(im_test)","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:35:32.980779Z","iopub.execute_input":"2025-06-03T14:35:32.98108Z","iopub.status.idle":"2025-06-03T14:35:33.322861Z","shell.execute_reply.started":"2025-06-03T14:35:32.981032Z","shell.execute_reply":"2025-06-03T14:35:33.32187Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig , ax = plt.subplots(4, 4, figsize=(30, 25))\n\nfor i, axis in enumerate(ax.flat):\n    axis.imshow(im_test[i][:, :, 0], cmap='gray')\n    pred_class = im_pred[i].argmax()\n    pred_prob = im_pred[i].max() * 100\n\n    axis.set_title(f'Predict: {category[pred_class]}\\n Confidence: {pred_prob:.1f}%', fontsize=18)","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:35:36.813689Z","iopub.execute_input":"2025-06-03T14:35:36.813956Z","iopub.status.idle":"2025-06-03T14:35:39.167294Z","shell.execute_reply.started":"2025-06-03T14:35:36.813914Z","shell.execute_reply":"2025-06-03T14:35:39.166523Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 保存模型\nmodel.save_weights(MODEL_NAME)","metadata":{"execution":{"iopub.status.busy":"2025-06-03T14:35:40.603701Z","iopub.execute_input":"2025-06-03T14:35:40.603969Z","iopub.status.idle":"2025-06-03T14:35:40.791384Z","shell.execute_reply.started":"2025-06-03T14:35:40.603927Z","shell.execute_reply":"2025-06-03T14:35:40.790788Z"},"trusted":true,"editable":false},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true,"editable":false},"outputs":[],"execution_count":null}]}