├── .gitignore ├── Final_Presentation └── Deficiency_Detection.pdf ├── Images ├── All-In-One CNN │ ├── Single_CNN_Model_Metrics.pdf │ ├── crack_classification_cnn_accuracy.pdf │ └── crack_classification_cnn_loss.pdf ├── General_Classification │ ├── General_Classification_CNN_Model_Metrics.pdf │ ├── general_classification_cnn_accuracy.pdf │ └── general_classification_cnn_loss.pdf ├── Material_Classification │ ├── material_classification_cnn_accuracy.pdf │ └── material_classification_cnn_loss.pdf ├── Prediction_Probabilities │ ├── Prediction_Probabilities_Slide.jpg │ ├── crack_prediction_probabilities.pdf │ ├── crack_prediction_probabilities_zoom.pdf │ ├── general_prediction_probabilities.pdf │ ├── general_prediction_probabilities_zoom.pdf │ ├── material_prediction_probabilities.pdf │ └── material_prediction_probabilities_zoom.pdf ├── Separate_CNNs │ ├── crack_classification_brick_accuracy.pdf │ ├── crack_classification_brick_loss.pdf │ ├── crack_classification_concrete_accuracy.pdf │ ├── crack_classification_concrete_loss.pdf │ ├── crack_classification_drywall_accuracy.pdf │ ├── crack_classification_drywall_loss.pdf │ ├── crack_classification_glass_accuracy.pdf │ ├── crack_classification_glass_loss.pdf │ ├── crack_classification_tile_accuracy.pdf │ └── crack_classification_tile_loss.pdf ├── Slides │ ├── 1-General-Vs-Specific.jpg │ ├── 2-Material-Type.jpg │ ├── 3-Crack-Classification.jpg │ ├── Deficient-Cracking.jpg │ ├── Deficient-Work.jpg │ └── Title-Slide.jpg ├── cnn_InceptionResNetV2_tuned_accuracy.pdf ├── cnn_InceptionResNetV2_tuned_loss.pdf ├── cnn_VGG19_tuned_accuracy.pdf ├── cnn_VGG19_tuned_loss.pdf ├── cnn_vanilla_tuned_accuracy.pdf └── cnn_vanilla_tuned_loss.pdf ├── Jupyter_Notebooks ├── 0 - Project Overview.ipynb ├── 1 - Convolutional Neural Network.ipynb ├── 2 - Convolutional Neural Network With InceptionResNetV2 Base.ipynb ├── 3 - Convolutional Neural Network With VGG19 Base.ipynb ├── 4 - InceptionResNetV2 Transfer Learning CNN + Challenging Dataset.ipynb ├── 5 - Exploratory Data Analysis.ipynb ├── 6 - Material Classification.ipynb ├── 7 - Crack Classification - Separate CNNs.ipynb ├── 8 - Crack Classification - One CNN.ipynb └── 9 - General Vs. Material Classification.ipynb ├── Project_Prompt ├── Flatiron Data Science Capstone Project Guidelines.pdf └── Flatiron Data Science Capstone Project Timeline.pdf ├── Py_Files ├── __init__.py ├── image_size_stats.py ├── imports.py └── max_range.py ├── README.md └── Web_Application ├── Deficiency-Detection-Demo.gif ├── Deficiency-Detection-Demo.mov └── Py_Files ├── Crack_Testing.py ├── General_Testing.py ├── Material_Testing.py └── deficiency-detection.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /Final_Presentation/Deficiency_Detection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Final_Presentation/Deficiency_Detection.pdf -------------------------------------------------------------------------------- /Images/All-In-One CNN/Single_CNN_Model_Metrics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/All-In-One CNN/Single_CNN_Model_Metrics.pdf -------------------------------------------------------------------------------- /Images/All-In-One CNN/crack_classification_cnn_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/All-In-One CNN/crack_classification_cnn_accuracy.pdf -------------------------------------------------------------------------------- /Images/All-In-One CNN/crack_classification_cnn_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/All-In-One CNN/crack_classification_cnn_loss.pdf -------------------------------------------------------------------------------- /Images/General_Classification/General_Classification_CNN_Model_Metrics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/General_Classification/General_Classification_CNN_Model_Metrics.pdf -------------------------------------------------------------------------------- /Images/General_Classification/general_classification_cnn_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/General_Classification/general_classification_cnn_accuracy.pdf -------------------------------------------------------------------------------- /Images/General_Classification/general_classification_cnn_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/General_Classification/general_classification_cnn_loss.pdf -------------------------------------------------------------------------------- /Images/Material_Classification/material_classification_cnn_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Material_Classification/material_classification_cnn_accuracy.pdf -------------------------------------------------------------------------------- /Images/Material_Classification/material_classification_cnn_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Material_Classification/material_classification_cnn_loss.pdf -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/Prediction_Probabilities_Slide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/Prediction_Probabilities_Slide.jpg -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/crack_prediction_probabilities.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/crack_prediction_probabilities.pdf -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/crack_prediction_probabilities_zoom.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/crack_prediction_probabilities_zoom.pdf -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/general_prediction_probabilities.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/general_prediction_probabilities.pdf -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/general_prediction_probabilities_zoom.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/general_prediction_probabilities_zoom.pdf -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/material_prediction_probabilities.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/material_prediction_probabilities.pdf -------------------------------------------------------------------------------- /Images/Prediction_Probabilities/material_prediction_probabilities_zoom.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Prediction_Probabilities/material_prediction_probabilities_zoom.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_brick_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_brick_accuracy.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_brick_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_brick_loss.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_concrete_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_concrete_accuracy.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_concrete_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_concrete_loss.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_drywall_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_drywall_accuracy.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_drywall_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_drywall_loss.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_glass_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_glass_accuracy.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_glass_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_glass_loss.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_tile_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_tile_accuracy.pdf -------------------------------------------------------------------------------- /Images/Separate_CNNs/crack_classification_tile_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Separate_CNNs/crack_classification_tile_loss.pdf -------------------------------------------------------------------------------- /Images/Slides/1-General-Vs-Specific.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Slides/1-General-Vs-Specific.jpg -------------------------------------------------------------------------------- /Images/Slides/2-Material-Type.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Slides/2-Material-Type.jpg -------------------------------------------------------------------------------- /Images/Slides/3-Crack-Classification.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Slides/3-Crack-Classification.jpg -------------------------------------------------------------------------------- /Images/Slides/Deficient-Cracking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Slides/Deficient-Cracking.jpg -------------------------------------------------------------------------------- /Images/Slides/Deficient-Work.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Slides/Deficient-Work.jpg -------------------------------------------------------------------------------- /Images/Slides/Title-Slide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/Slides/Title-Slide.jpg -------------------------------------------------------------------------------- /Images/cnn_InceptionResNetV2_tuned_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/cnn_InceptionResNetV2_tuned_accuracy.pdf -------------------------------------------------------------------------------- /Images/cnn_InceptionResNetV2_tuned_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/cnn_InceptionResNetV2_tuned_loss.pdf -------------------------------------------------------------------------------- /Images/cnn_VGG19_tuned_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/cnn_VGG19_tuned_accuracy.pdf -------------------------------------------------------------------------------- /Images/cnn_VGG19_tuned_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/cnn_VGG19_tuned_loss.pdf -------------------------------------------------------------------------------- /Images/cnn_vanilla_tuned_accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/cnn_vanilla_tuned_accuracy.pdf -------------------------------------------------------------------------------- /Images/cnn_vanilla_tuned_loss.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Images/cnn_vanilla_tuned_loss.pdf -------------------------------------------------------------------------------- /Jupyter_Notebooks/0 - Project Overview.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Project Overview" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "___" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "toc": true 21 | }, 22 | "source": [ 23 | "

Table of Contents

\n", 24 | "
" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "___" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "## Question" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "**Can a Convolutional Neural Network detect and classify architectural and structural surface deficiencies in concrete?**" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "___" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "## Goals" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "1. Rapidly identify images of architectural and structural surfaces that show deterioration or damage.\n", 67 | "2. Build a web-app or mobile app that can be used to process these images." 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "___" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "## Real-World Application" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "

Rapid Identification Of Deficient Construction Work.

\n", 89 | "\n", 90 | "- Architects and engineers visit project sites regularly to check in on general construction progress and to identify any **deficient work.**\n", 91 | " - For example: cracked concrete, chipped tile work, scratched finishes, etc...\n", 92 | " \n", 93 | " \n", 94 | "- **Photography** is the primary medium to document site conditions. \n", 95 | " - If the project is large, then hundreds or thousands of photos can be taken on a single site visit!\n", 96 | " \n", 97 | " \n", 98 | "- A selection of these photos is used to generate a **\"field report\".** \n", 99 | " - The field report summarizes progress since the last visit and identifies any areas of deficient work.\n", 100 | "\n", 101 | "\n", 102 | "- Often times, it is very time-consuming to manually pore through all of the photos taken to find all of the images that capture deficient work.\n", 103 | " - This can take a lot of time - and this is time that can be saved by a **Convolutional Neural Network.**\n", 104 | " \n", 105 | " \n", 106 | "- As an immediate use case, across a large architecture/engineering firm, or even a construction company, **this tool would save hundreds to thousands of hours of labor per year, and therefore would save many thousands of dollars.**\n", 107 | "\n", 108 | "\n", 109 | "- Further into future, perhaps drones could fly through a construction site, and take photos and auto-identify problem areas using this CNN!" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "___" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "## Methodology" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "- Text" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "## Evaluation" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": {}, 143 | "source": [ 144 | "- The most important thing is to capture as many of the deficiencies as possible.\n", 145 | "\n", 146 | "\n", 147 | "- **Missing deficiencies is potentially a safety issue on a construction site.**\n", 148 | " - We don't want to let anything \"slip through the cracks\".\n", 149 | " \n", 150 | " \n", 151 | "- So then, probably the most important metric to evaluate \"success\" would be to measure:\n", 152 | " - **Recall**\n", 153 | " - **False Negative Rate**\n", 154 | " \n", 155 | " \n", 156 | "- However, we don't want to simply classify all images as \"deficient\".\n", 157 | " - Then we aren't saving architects and engineers any time or effort!\n", 158 | " \n", 159 | " \n", 160 | "- So perhaps we would consider using **F1-Score** instead since it balances accuracy and recall so the model doesn't just classify everything as deficient." 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [] 169 | } 170 | ], 171 | "metadata": { 172 | "kernelspec": { 173 | "display_name": "Python 3", 174 | "language": "python", 175 | "name": "python3" 176 | }, 177 | "language_info": { 178 | "codemirror_mode": { 179 | "name": "ipython", 180 | "version": 3 181 | }, 182 | "file_extension": ".py", 183 | "mimetype": "text/x-python", 184 | "name": "python", 185 | "nbconvert_exporter": "python", 186 | "pygments_lexer": "ipython3", 187 | "version": "3.7.4" 188 | }, 189 | "toc": { 190 | "base_numbering": 1, 191 | "nav_menu": {}, 192 | "number_sections": true, 193 | "sideBar": true, 194 | "skip_h1_title": true, 195 | "title_cell": "Table of Contents", 196 | "title_sidebar": "Contents", 197 | "toc_cell": true, 198 | "toc_position": {}, 199 | "toc_section_display": true, 200 | "toc_window_display": true 201 | } 202 | }, 203 | "nbformat": 4, 204 | "nbformat_minor": 2 205 | } 206 | -------------------------------------------------------------------------------- /Jupyter_Notebooks/3 - Convolutional Neural Network With VGG19 Base.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Convolutional Neural Network With VGG19 Base" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": { 13 | "toc": true 14 | }, 15 | "source": [ 16 | "

Table of Contents

\n", 17 | "
" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "heading_collapsed": true 24 | }, 25 | "source": [ 26 | "## Setup" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "heading_collapsed": true, 33 | "hidden": true 34 | }, 35 | "source": [ 36 | "### Import Libraries" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 2, 42 | "metadata": { 43 | "hidden": true 44 | }, 45 | "outputs": [], 46 | "source": [ 47 | "# Import necessary python packages and functions\n", 48 | "\n", 49 | "from __future__ import print_function\n", 50 | "import sys\n", 51 | "sys.path.append(\"..\")\n", 52 | "import matplotlib.pyplot as plt\n", 53 | "import matplotlib.ticker as ticker\n", 54 | "import seaborn as sns\n", 55 | "import numpy as np\n", 56 | "import pandas as pd\n", 57 | "import requests\n", 58 | "import json\n", 59 | "import math\n", 60 | "import sklearn\n", 61 | "from scipy import stats\n", 62 | "from scipy.stats import norm\n", 63 | "from sklearn.utils import resample\n", 64 | "import pickle\n", 65 | "import statsmodels.api as sm\n", 66 | "from statsmodels.formula.api import ols\n", 67 | "import scipy.stats as stats\n", 68 | "from wordcloud import WordCloud\n", 69 | "import random\n", 70 | "from collections import Counter\n", 71 | "from statsmodels.stats.outliers_influence import variance_inflation_factor\n", 72 | "from sklearn.model_selection import train_test_split, GridSearchCV, RandomizedSearchCV, cross_val_score, cross_validate\n", 73 | "from sklearn.linear_model import LassoCV, Lasso, Ridge, LinearRegression, LogisticRegression\n", 74 | "from sklearn.preprocessing import StandardScaler\n", 75 | "from sklearn.linear_model import SGDClassifier\n", 76 | "from sklearn.metrics import roc_curve, auc, confusion_matrix, roc_auc_score, precision_recall_curve, precision_recall_fscore_support\n", 77 | "import scipy.stats as stats\n", 78 | "from sklearn.preprocessing import OneHotEncoder\n", 79 | "from sklearn.ensemble import RandomForestClassifier\n", 80 | "from imblearn.over_sampling import SMOTE, ADASYN\n", 81 | "from pprint import pprint\n", 82 | "import keras\n", 83 | "from keras.preprocessing import image\n", 84 | "from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img\n", 85 | "from keras.models import Sequential, load_model, Input, Model\n", 86 | "from keras.layers.core import Dense, Dropout, Activation, Flatten\n", 87 | "from keras.layers import Conv2D, MaxPooling2D, BatchNormalization\n", 88 | "from keras.utils import np_utils\n", 89 | "from keras import backend, layers, models\n", 90 | "from PIL import Image\n", 91 | "import imageio\n", 92 | "import os\n", 93 | "%matplotlib inline" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": { 99 | "heading_collapsed": true, 100 | "hidden": true 101 | }, 102 | "source": [ 103 | "### Expand max rows, columns, width" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 3, 109 | "metadata": { 110 | "hidden": true 111 | }, 112 | "outputs": [], 113 | "source": [ 114 | "#Expanding max range in Pandas (common practice)\n", 115 | "pd.set_option('display.max_rows',5000)\n", 116 | "pd.set_option('display.max_columns', 5000)\n", 117 | "pd.set_option('display.width', 5000)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": { 123 | "heading_collapsed": true, 124 | "hidden": true 125 | }, 126 | "source": [ 127 | "### Configure OS to reduce messages" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 4, 133 | "metadata": { 134 | "hidden": true 135 | }, 136 | "outputs": [], 137 | "source": [ 138 | "# This is to avoid getting hundreds of log messages\n", 139 | "os.environ['TF_CPP_MIN_LOG_LEVEL']='3'" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": { 145 | "heading_collapsed": true 146 | }, 147 | "source": [ 148 | "## Import Data" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": { 154 | "heading_collapsed": true, 155 | "hidden": true 156 | }, 157 | "source": [ 158 | "### Assign all data to train, validation, and test" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 5, 164 | "metadata": { 165 | "hidden": true 166 | }, 167 | "outputs": [ 168 | { 169 | "name": "stdout", 170 | "output_type": "stream", 171 | "text": [ 172 | "Found 30000 images belonging to 2 classes.\n", 173 | "Found 5000 images belonging to 2 classes.\n", 174 | "Found 5000 images belonging to 2 classes.\n" 175 | ] 176 | } 177 | ], 178 | "source": [ 179 | "# Get all the data in the directory, and reshape images.\n", 180 | "# NOTE: images are already a consistent size - 227 x 227\n", 181 | "# Multiply every value by 1/255 (this is scaling the data on a scale between 0-1)\n", 182 | "# SHUFFLE!\n", 183 | "\n", 184 | "data_train = ImageDataGenerator(rescale=1/255).flow_from_directory( \n", 185 | " '/Users/alexandercheng/Desktop/code/projects/crack-detection-data/Data/Train',\n", 186 | " target_size=(256, 256), #squish images down to this size (images are already this size)\n", 187 | " batch_size=30000, #we want batch size to be all of the images in the folder\n", 188 | " shuffle=True,\n", 189 | " seed=123)\n", 190 | "\n", 191 | "data_validation = ImageDataGenerator(rescale=1/255).flow_from_directory( \n", 192 | " '/Users/alexandercheng/Desktop/code/projects/crack-detection-data/Data/Validation',\n", 193 | " target_size=(256, 256),\n", 194 | " batch_size=5000,\n", 195 | " shuffle=True,\n", 196 | " seed=123)\n", 197 | "\n", 198 | "data_test = ImageDataGenerator(rescale=1/255).flow_from_directory( \n", 199 | " '/Users/alexandercheng/Desktop/code/projects/crack-detection-data/Data/Test',\n", 200 | " target_size=(256, 256),\n", 201 | " batch_size=5000,\n", 202 | " shuffle=True,\n", 203 | " seed=123)" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": { 209 | "heading_collapsed": true, 210 | "hidden": true 211 | }, 212 | "source": [ 213 | "### Get images & labels assigned to variables" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": 6, 219 | "metadata": { 220 | "hidden": true 221 | }, 222 | "outputs": [], 223 | "source": [ 224 | "# Split images and labels\n", 225 | "\n", 226 | "images_train, labels_train = next(data_train)\n", 227 | "images_validation, labels_validation = next(data_validation)\n", 228 | "images_test, labels_test = next(data_test)" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 7, 234 | "metadata": { 235 | "hidden": true 236 | }, 237 | "outputs": [ 238 | { 239 | "name": "stdout", 240 | "output_type": "stream", 241 | "text": [ 242 | "TRAIN\n", 243 | "Images Shape (30000, 256, 256, 3)\n", 244 | "Labels Shape (30000, 2)\n", 245 | "VALIDATION\n", 246 | "Images Shape (5000, 256, 256, 3)\n", 247 | "Labels Shape (5000, 2)\n", 248 | "TEST\n", 249 | "Images Shape (5000, 256, 256, 3)\n", 250 | "Labels Shape (5000, 2)\n" 251 | ] 252 | } 253 | ], 254 | "source": [ 255 | "# Check image and label shape.\n", 256 | "# Each image should now be reshaped into 256 pixels x 256 pixels x 3 colors (RGB).\n", 257 | "\n", 258 | "print('TRAIN')\n", 259 | "print('Images Shape', images_train.shape) #(30,000, 256, 256, 3)\n", 260 | "print('Labels Shape', labels_train.shape) #(30,000, 2)\n", 261 | "print('VALIDATION')\n", 262 | "print('Images Shape', images_validation.shape) #(5,000, 256, 256, 3)\n", 263 | "print('Labels Shape', labels_validation.shape)#(5,000, 2)\n", 264 | "print('TEST')\n", 265 | "print('Images Shape', images_test.shape) #(5,000, 256, 256, 3)\n", 266 | "print('Labels Shape', labels_test.shape) #(5,000, 2)" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": { 272 | "heading_collapsed": true, 273 | "hidden": true 274 | }, 275 | "source": [ 276 | "### Create Keras \"Callbacks\" To Customize Training + Output" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 8, 282 | "metadata": { 283 | "hidden": true 284 | }, 285 | "outputs": [], 286 | "source": [ 287 | "saving_weights = keras.callbacks.ModelCheckpoint(\n", 288 | " 'weights.{epoch:02d}-{val_loss:.2f}.hdf5', #save our output as we go through.\n", 289 | " monitor='val_loss', verbose=0, save_best_only=False, #for each epoch, give me the validation loss.\n", 290 | " save_weights_only=False, mode='auto', period=10)\n", 291 | "\n", 292 | "reduce_lr = keras.callbacks.ReduceLROnPlateau( #lr = learning rate - we want a big step size up front to speed up the process, but smaller steps later on to ensure we don't overshoot the minimum)\n", 293 | " monitor='val_loss', factor=0.1, patience=20,\n", 294 | " verbose=0, mode='auto', min_delta=0.0001, min_lr=0)\n", 295 | "\n", 296 | "nan_problem = keras.callbacks.TerminateOnNaN()\n", 297 | "\n", 298 | "early_stop = keras.callbacks.EarlyStopping(\n", 299 | " monitor='val_loss', min_delta=0, patience=20,\n", 300 | " verbose=0, mode='auto', baseline=None, restore_best_weights=False)\n", 301 | "\n", 302 | "csv_logger = keras.callbacks.CSVLogger('training.log') #write information about my model to a file" 303 | ] 304 | }, 305 | { 306 | "cell_type": "markdown", 307 | "metadata": { 308 | "heading_collapsed": true 309 | }, 310 | "source": [ 311 | "## Build The CNN" 312 | ] 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "metadata": { 317 | "heading_collapsed": true, 318 | "hidden": true 319 | }, 320 | "source": [ 321 | "### Load Pre-Trained Model" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": { 327 | "hidden": true 328 | }, 329 | "source": [ 330 | "**Which pre-trained model to use?**\n", 331 | "\n", 332 | "- **NASNetLarge** \n", 333 | " - This model has the highest \"top 1\" and \"top 5\" accuracy on Keras documentation.\n", 334 | " - But unfortunately...NASNetLarge(weights='imagenet') is forced to take only input_shape=(331, 331, 3).\n", 335 | " - This is larger than our dataset's original image size...so we will choose a different base model.\n", 336 | "- **InceptionResNetV2**\n", 337 | " - InceptionResNetV2 - has the 2nd highest \"top 1\" and \"top 5\" accuracy on Keras documentation.\n", 338 | " - We wil try this model instead of NASNetLarge" 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": 9, 344 | "metadata": { 345 | "hidden": true 346 | }, 347 | "outputs": [], 348 | "source": [ 349 | "from keras.applications import VGG19" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": 10, 355 | "metadata": { 356 | "hidden": true 357 | }, 358 | "outputs": [ 359 | { 360 | "name": "stdout", 361 | "output_type": "stream", 362 | "text": [ 363 | "Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5\n", 364 | "80142336/80134624 [==============================] - 12s 0us/step\n" 365 | ] 366 | } 367 | ], 368 | "source": [ 369 | "cnn_base = VGG19(weights='imagenet', #None or \"imagenet\" - we want \"imagenet\" because we want the trained weights.\n", 370 | " include_top=False, #allows us to specify the input shape of our images\n", 371 | " input_shape=(256, 256, 3)) #since \"include_top=False\" we need to provide an input shape for our incoming image data." 372 | ] 373 | }, 374 | { 375 | "cell_type": "markdown", 376 | "metadata": { 377 | "heading_collapsed": true, 378 | "hidden": true 379 | }, 380 | "source": [ 381 | "### Build Model On Top Of Pre-Trained Model" 382 | ] 383 | }, 384 | { 385 | "cell_type": "markdown", 386 | "metadata": { 387 | "hidden": true 388 | }, 389 | "source": [ 390 | "**NOTES ON BUILDING THE CNN**\n", 391 | "\n", 392 | "- **Activation Functions**\n", 393 | " - **If you have a multi-label classification problem and there is more than one \"right answer\" and the outputs are NOT mutually exclusive, then use a sigmoid function** on each raw output independently. The sigmoid will allow you to have high probability for all of your classes, some of them, or none of them. Example: classifying diseases in a chest x-ray image. The image might contain pneumonia, emphysema, and/or cancer, or none of those findings.\n", 394 | " - **If you have a multi-class classification problem and there is only one \"right answer\" and the outputs are mutually exclusive, then use a softmax function.** The softmax will enforce that the sum of the probabilities of your output classes are equal to one, so in order to increase the probability of a particular class, your model must correspondingly decrease the probability of at least one of the other classes. Example: classifying images from the MNIST data set of handwritten digits. A single picture of a digit has only one true identity - the picture cannot be a 7 and an 8 at the same time." 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": 11, 400 | "metadata": { 401 | "hidden": true 402 | }, 403 | "outputs": [], 404 | "source": [ 405 | "cnn_3 = models.Sequential() #instantiate model\n", 406 | "\n", 407 | "cnn_3.add(cnn_base) #add VGG19 pre-trained model without top\n", 408 | "\n", 409 | "cnn_3.add(layers.Conv2D(64, (3, 3), #64 different filters, with a 3x3 filter.\n", 410 | " activation='relu', #use ReLu activation functions throughout, save sigmoid / softmax function for the end layer.\n", 411 | " input_shape=(256, 256, 3), #image shape input\n", 412 | " padding='SAME')) #\"valid\" means no padding, and \"same\" means with padding.\n", 413 | "\n", 414 | "# 64 bias parameters.\n", 415 | "# 64 * (3 * 3 * 3) weight parametrs.\n", 416 | "# Output is 64*256*256.\n", 417 | "\n", 418 | "cnn_3.add(layers.MaxPooling2D((2, 2))) #(2,2) reduces dimensionality of image by half.\n", 419 | "\n", 420 | "# Output is 64*128*128.\n", 421 | "# 32 nodes in this layer...no padding here.\n", 422 | "# Adding padding='SAME' here because InceptionResNetV2 downsamples the input image very aggressively...\n", 423 | "# And we would otherwise get a negative dimension size in the next pooling step.\n", 424 | "cnn_3.add(layers.Conv2D(32, (3, 3), activation='relu', padding='SAME')) \n", 425 | "\n", 426 | "# 32 bias parameters.\n", 427 | "# 32 * (3*3*64).\n", 428 | "# Output is 32*128*128.\n", 429 | "\n", 430 | "cnn_3.add(layers.MaxPooling2D((2, 2))) \n", 431 | "\n", 432 | "# Output is 32*64*64.\n", 433 | "# Flattening is converting the data into a 1-dimensional array for inputting it to the next layer. \n", 434 | "# We flatten the output of the convolutional layers to create a single long feature vector. \n", 435 | "# 32 x 64 x 64 = 131,072 features once flattened.\n", 436 | "cnn_3.add(layers.Flatten())\n", 437 | "\n", 438 | "# And the flattened data is connected to the final classification, fully-connected layers.\n", 439 | "# We simply put all the pixel data in one line and make connections with the final layer. \n", 440 | "# Dense fully connected layer.\n", 441 | "cnn_3.add(layers.Dense(32, activation='relu')) \n", 442 | "\n", 443 | "# Final layer does the classification.\n", 444 | "# A material cannot be both \"not cracked\" and \"cracked\" - it is either one or the other.\n", 445 | "# So we use a \"Softmax\" function for classification where there is only 1 \"right answer\".\n", 446 | "cnn_3.add(layers.Dense(2, activation='softmax')) " 447 | ] 448 | }, 449 | { 450 | "cell_type": "markdown", 451 | "metadata": { 452 | "heading_collapsed": true 453 | }, 454 | "source": [ 455 | "## Freezing The Base" 456 | ] 457 | }, 458 | { 459 | "cell_type": "markdown", 460 | "metadata": { 461 | "hidden": true 462 | }, 463 | "source": [ 464 | "### Examine Layers Of CNN" 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": 12, 470 | "metadata": { 471 | "hidden": true 472 | }, 473 | "outputs": [ 474 | { 475 | "name": "stdout", 476 | "output_type": "stream", 477 | "text": [ 478 | "There are 40 trainable weights.\n", 479 | "\n", 480 | "There are 8 trainable layers.\n", 481 | "\n", 482 | "vgg19 True\n", 483 | "conv2d_1 True\n", 484 | "max_pooling2d_1 True\n", 485 | "conv2d_2 True\n", 486 | "max_pooling2d_2 True\n", 487 | "flatten_1 True\n", 488 | "dense_1 True\n", 489 | "dense_2 True\n" 490 | ] 491 | } 492 | ], 493 | "source": [ 494 | "#Check how many trainable weights are in the model\n", 495 | "print('There are', len(cnn_3.trainable_weights), 'trainable weights.')\n", 496 | "print()\n", 497 | "\n", 498 | "# Check how many layers are trainable\n", 499 | "print('There are', len(cnn_3.layers), 'trainable layers.')\n", 500 | "print()\n", 501 | "\n", 502 | "# Check which layers are trainable\n", 503 | "for layer in cnn_3.layers:\n", 504 | " print(layer.name, layer.trainable)" 505 | ] 506 | }, 507 | { 508 | "cell_type": "markdown", 509 | "metadata": { 510 | "hidden": true 511 | }, 512 | "source": [ 513 | "### Freeze Base CNN model" 514 | ] 515 | }, 516 | { 517 | "cell_type": "code", 518 | "execution_count": 14, 519 | "metadata": { 520 | "hidden": true 521 | }, 522 | "outputs": [ 523 | { 524 | "name": "stdout", 525 | "output_type": "stream", 526 | "text": [ 527 | "vgg19 False\n", 528 | "conv2d_1 True\n", 529 | "max_pooling2d_1 True\n", 530 | "conv2d_2 True\n", 531 | "max_pooling2d_2 True\n", 532 | "flatten_1 True\n", 533 | "dense_1 True\n", 534 | "dense_2 True\n" 535 | ] 536 | } 537 | ], 538 | "source": [ 539 | "#freeze the base_cnn model, and double-check to make sure it's frozen.\n", 540 | "cnn_base.trainable = False\n", 541 | "for layer in cnn_3.layers:\n", 542 | " print(layer.name, layer.trainable)" 543 | ] 544 | }, 545 | { 546 | "cell_type": "markdown", 547 | "metadata": { 548 | "heading_collapsed": true 549 | }, 550 | "source": [ 551 | "## Fine-Tuning" 552 | ] 553 | }, 554 | { 555 | "cell_type": "markdown", 556 | "metadata": { 557 | "heading_collapsed": true, 558 | "hidden": true 559 | }, 560 | "source": [ 561 | "### Take a look at the base CNN architecture" 562 | ] 563 | }, 564 | { 565 | "cell_type": "code", 566 | "execution_count": 17, 567 | "metadata": { 568 | "hidden": true 569 | }, 570 | "outputs": [], 571 | "source": [ 572 | "cnn_base.trainable = True" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": 18, 578 | "metadata": { 579 | "hidden": true 580 | }, 581 | "outputs": [ 582 | { 583 | "name": "stdout", 584 | "output_type": "stream", 585 | "text": [ 586 | "Model: \"vgg19\"\n", 587 | "_________________________________________________________________\n", 588 | "Layer (type) Output Shape Param # \n", 589 | "=================================================================\n", 590 | "input_1 (InputLayer) (None, 256, 256, 3) 0 \n", 591 | "_________________________________________________________________\n", 592 | "block1_conv1 (Conv2D) (None, 256, 256, 64) 1792 \n", 593 | "_________________________________________________________________\n", 594 | "block1_conv2 (Conv2D) (None, 256, 256, 64) 36928 \n", 595 | "_________________________________________________________________\n", 596 | "block1_pool (MaxPooling2D) (None, 128, 128, 64) 0 \n", 597 | "_________________________________________________________________\n", 598 | "block2_conv1 (Conv2D) (None, 128, 128, 128) 73856 \n", 599 | "_________________________________________________________________\n", 600 | "block2_conv2 (Conv2D) (None, 128, 128, 128) 147584 \n", 601 | "_________________________________________________________________\n", 602 | "block2_pool (MaxPooling2D) (None, 64, 64, 128) 0 \n", 603 | "_________________________________________________________________\n", 604 | "block3_conv1 (Conv2D) (None, 64, 64, 256) 295168 \n", 605 | "_________________________________________________________________\n", 606 | "block3_conv2 (Conv2D) (None, 64, 64, 256) 590080 \n", 607 | "_________________________________________________________________\n", 608 | "block3_conv3 (Conv2D) (None, 64, 64, 256) 590080 \n", 609 | "_________________________________________________________________\n", 610 | "block3_conv4 (Conv2D) (None, 64, 64, 256) 590080 \n", 611 | "_________________________________________________________________\n", 612 | "block3_pool (MaxPooling2D) (None, 32, 32, 256) 0 \n", 613 | "_________________________________________________________________\n", 614 | "block4_conv1 (Conv2D) (None, 32, 32, 512) 1180160 \n", 615 | "_________________________________________________________________\n", 616 | "block4_conv2 (Conv2D) (None, 32, 32, 512) 2359808 \n", 617 | "_________________________________________________________________\n", 618 | "block4_conv3 (Conv2D) (None, 32, 32, 512) 2359808 \n", 619 | "_________________________________________________________________\n", 620 | "block4_conv4 (Conv2D) (None, 32, 32, 512) 2359808 \n", 621 | "_________________________________________________________________\n", 622 | "block4_pool (MaxPooling2D) (None, 16, 16, 512) 0 \n", 623 | "_________________________________________________________________\n", 624 | "block5_conv1 (Conv2D) (None, 16, 16, 512) 2359808 \n", 625 | "_________________________________________________________________\n", 626 | "block5_conv2 (Conv2D) (None, 16, 16, 512) 2359808 \n", 627 | "_________________________________________________________________\n", 628 | "block5_conv3 (Conv2D) (None, 16, 16, 512) 2359808 \n", 629 | "_________________________________________________________________\n", 630 | "block5_conv4 (Conv2D) (None, 16, 16, 512) 2359808 \n", 631 | "_________________________________________________________________\n", 632 | "block5_pool (MaxPooling2D) (None, 8, 8, 512) 0 \n", 633 | "=================================================================\n", 634 | "Total params: 20,024,384\n", 635 | "Trainable params: 20,024,384\n", 636 | "Non-trainable params: 0\n", 637 | "_________________________________________________________________\n" 638 | ] 639 | } 640 | ], 641 | "source": [ 642 | "cnn_base.summary()" 643 | ] 644 | }, 645 | { 646 | "cell_type": "markdown", 647 | "metadata": { 648 | "heading_collapsed": true, 649 | "hidden": true 650 | }, 651 | "source": [ 652 | "### Refreeze all layers except for last block of base_cnn" 653 | ] 654 | }, 655 | { 656 | "cell_type": "code", 657 | "execution_count": 19, 658 | "metadata": { 659 | "hidden": true 660 | }, 661 | "outputs": [], 662 | "source": [ 663 | "# Unfreeze cnn_base.\n", 664 | "cnn_base.trainable = True \n", 665 | "\n", 666 | "# Refreeze all layers except for the last block of layers.\n", 667 | "for layer in cnn_base.layers:\n", 668 | " if 'block5' in layer.name:\n", 669 | " layer.trainable = True\n", 670 | " else:\n", 671 | " layer.trainable = False" 672 | ] 673 | }, 674 | { 675 | "cell_type": "code", 676 | "execution_count": 21, 677 | "metadata": { 678 | "hidden": true 679 | }, 680 | "outputs": [ 681 | { 682 | "name": "stdout", 683 | "output_type": "stream", 684 | "text": [ 685 | "input_1 False\n", 686 | "block1_conv1 False\n", 687 | "block1_conv2 False\n", 688 | "block1_pool False\n", 689 | "block2_conv1 False\n", 690 | "block2_conv2 False\n", 691 | "block2_pool False\n", 692 | "block3_conv1 False\n", 693 | "block3_conv2 False\n", 694 | "block3_conv3 False\n", 695 | "block3_conv4 False\n", 696 | "block3_pool False\n", 697 | "block4_conv1 False\n", 698 | "block4_conv2 False\n", 699 | "block4_conv3 False\n", 700 | "block4_conv4 False\n", 701 | "block4_pool False\n", 702 | "block5_conv1 True\n", 703 | "block5_conv2 True\n", 704 | "block5_conv3 True\n", 705 | "block5_conv4 True\n", 706 | "block5_pool True\n" 707 | ] 708 | } 709 | ], 710 | "source": [ 711 | "#Double check that we unfroze only the last block of layers for the base_cnn.\n", 712 | "for layer in cnn_base.layers:\n", 713 | " print(layer.name, layer.trainable)" 714 | ] 715 | }, 716 | { 717 | "cell_type": "markdown", 718 | "metadata": {}, 719 | "source": [ 720 | "## Try 10 Epochs With Fine-Tuned Model" 721 | ] 722 | }, 723 | { 724 | "cell_type": "code", 725 | "execution_count": 22, 726 | "metadata": {}, 727 | "outputs": [], 728 | "source": [ 729 | "cnn_3.compile(loss='binary_crossentropy',\n", 730 | " optimizer=\"sgd\",\n", 731 | " metrics=['acc'])" 732 | ] 733 | }, 734 | { 735 | "cell_type": "code", 736 | "execution_count": 23, 737 | "metadata": {}, 738 | "outputs": [ 739 | { 740 | "name": "stdout", 741 | "output_type": "stream", 742 | "text": [ 743 | "Train on 30000 samples, validate on 5000 samples\n", 744 | "Epoch 1/10\n", 745 | "30000/30000 [==============================] - 4095s 136ms/step - loss: 0.1450 - acc: 0.9350 - val_loss: 0.0267 - val_acc: 0.9924\n", 746 | "Epoch 2/10\n", 747 | "30000/30000 [==============================] - 4075s 136ms/step - loss: 0.0239 - acc: 0.9930 - val_loss: 0.0233 - val_acc: 0.9922\n", 748 | "Epoch 3/10\n", 749 | "30000/30000 [==============================] - 4070s 136ms/step - loss: 0.0169 - acc: 0.9950 - val_loss: 0.0202 - val_acc: 0.9938\n", 750 | "Epoch 4/10\n", 751 | "30000/30000 [==============================] - 4084s 136ms/step - loss: 0.0143 - acc: 0.9954 - val_loss: 0.0136 - val_acc: 0.9960\n", 752 | "Epoch 5/10\n", 753 | "30000/30000 [==============================] - 4082s 136ms/step - loss: 0.0123 - acc: 0.9961 - val_loss: 0.0179 - val_acc: 0.9950\n", 754 | "Epoch 6/10\n", 755 | "30000/30000 [==============================] - 4082s 136ms/step - loss: 0.0102 - acc: 0.9968 - val_loss: 0.0165 - val_acc: 0.9958\n", 756 | "Epoch 7/10\n", 757 | "30000/30000 [==============================] - 4077s 136ms/step - loss: 0.0105 - acc: 0.9969 - val_loss: 0.0124 - val_acc: 0.9964\n", 758 | "Epoch 8/10\n", 759 | "30000/30000 [==============================] - 4079s 136ms/step - loss: 0.0089 - acc: 0.9974 - val_loss: 0.0129 - val_acc: 0.9960\n", 760 | "Epoch 9/10\n", 761 | "30000/30000 [==============================] - 4083s 136ms/step - loss: 0.3045 - acc: 0.9188 - val_loss: 0.0556 - val_acc: 0.9848\n", 762 | "Epoch 10/10\n", 763 | "30000/30000 [==============================] - 4077s 136ms/step - loss: 0.0415 - acc: 0.9876 - val_loss: 0.0319 - val_acc: 0.9902\n" 764 | ] 765 | } 766 | ], 767 | "source": [ 768 | "cnn_3c = cnn_3.fit(images_train,\n", 769 | " labels_train,\n", 770 | " epochs=10,\n", 771 | " batch_size=500,\n", 772 | " validation_data=(images_validation, labels_validation),\n", 773 | " callbacks=[csv_logger, early_stop, nan_problem, reduce_lr, saving_weights])" 774 | ] 775 | }, 776 | { 777 | "cell_type": "code", 778 | "execution_count": 24, 779 | "metadata": {}, 780 | "outputs": [], 781 | "source": [ 782 | "hist_cnn_3c = cnn_3c.history\n", 783 | "loss_values = hist_cnn_3c['loss']\n", 784 | "val_loss_values = hist_cnn_3c['val_loss']\n", 785 | "acc_values = hist_cnn_3c['acc']\n", 786 | "val_acc_values = hist_cnn_3c['val_acc']\n", 787 | "epochs = range(1, len(loss_values) + 1)" 788 | ] 789 | }, 790 | { 791 | "cell_type": "code", 792 | "execution_count": 36, 793 | "metadata": { 794 | "scrolled": false 795 | }, 796 | "outputs": [ 797 | { 798 | "data": { 799 | "image/png": "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fUZRURGlpaWsX7+emJgY3nvvPRISEhg4cCDz5s0jOzubnJwchg0bxu2338706dPp1q2b3r8rIuIEFeeA2zoobHPA9+/f79C/U8R51DNXCbZhQeCy/5JxVtd0w4YNGT58OA888AA+Pj7ExMRQVFREQUGBQ+7/0EMPcejQIeLi4ggNDaVZs2Z2vYI2e/fupUOHDsZ2XFwcCxYs4ODBgwwbNozS0lK6d+/Oo48+SlFREc888wxxcXF4e3sza9YsGjduzNChQxk+fDj+/v7ceuutDBs2zCFtEBGRKysoKLjqHPCoqCgaNGjg5KjkepmslxuD8xDFxcWkpqYSFRVlN6wIcPDgQe64444q3c82x8BiseDt7e30OQY1/W7Wr776CqvVSu/evcnLy+PBBx9k/fr1hISEOPxZjmpLdb5HR0tJSaFjx461GoMjeEo7QG1xRZ7SDnDvtuTk5PDGG29c8fj06dNr5H/zncGdvxebq+UtV6OeuSrw9vb26H+x3HbbbcyePZvXX38dgGnTprntf9QiInIpb2/vq84B1yII9+TUZC4pKYkVK1ZQWlrKuHHjGD16tN3xrVu38uabb1JWVkZ0dDQLFizAz8+P06dPM2vWLLKysrj11lt59dVXa7SHqq666aabeP/992s7DBERqSG2OeAV66baOHMOuDiW0xZApKens3z5ctauXUtiYiLr1q3j6NGjxvGCggIWLFjAu+++y2effUZxcTEff/wxUP66q1GjRpGcnExUVBRvv/22s8IWERHxGLY54H379jVKSfn7+9OvXz+nzgEXx3JaMrdr1y5iYmIICQkhICCA/v37k5ycbBwPCAhg+/btNG3alMLCQrKysggODsZsNvPdd9/Rv39/AIYOHWp3nYiIiFReQEAAZrOZIUOGGKNknTt3Vq+cG3NaMpeRkUFoaKixHRYWRnp6ut05vr6+7Nixg169enH+/Hm6d+/O+fPnCQoKwsenfEQ4NDT0kutERESk8vbu3cvatWv5xz/+wRdffKEeOTfntDlzZWVldjXLrFbrZWuY3XfffezZs4dly5Yxf/58Zs+efcl5la19ZpOamnrJPh8fn8u+PcHVuWPMV+KItpSUlJCSkuKAaK6PK8TgCJ7SDlBbXJGntAPcuy1ms9mupNXp06fduj0VeUo7qsppyVxERAR79+41tjMzMwkLCzO2c3JySE1NpXv37kB57bIZM2bQuHFj8vLyjHIgv72uMq5UmqSqiygsZgsF5wqwlFjw9vMmoGkA3r6eU5rEmRzVFj8/P6MGYG3xhOXw4DntALXFFXlKO8D923L69GmgfKQrOzubkpIS7rjjDrcfZnX37wX+X2mSqnLaMGvXrl3ZvXs32dnZRrXpnj17GsetViuzZs0yfmTJycncfffd+Pr60qlTJzZt2gRAYmKi3XXOUpBVwLdvfcuK6BW80eINVkSv4Nu3vqUg6/oL9j7yyCN89tln9s8rKKBLly5kZ2df8boxY8awZ88e/u///o+5c+decvzkyZP06dPnqs8+cOAAS5cuBWDbtm1XrT9UWXPmzGHDhg3XfR8REXG8rKwsoPw93kFBQQCcO3euNkOS6+S0nrnw8HBmzJjB2LFjMZvNDB8+nHbt2jFhwgSmTZtGdHQ0Cxcu5Mknn8RkMtGqVStefvllAObNm8ecOXNYsWIFN9xwA8uWLXNW2EB5j9z+f+5nyzP/byl3YVahsd35qc7X1UM3bNgwkpKSeOCBB4x9W7ZsoUuXLjRu3Pia10dHRxMdHV2tZx89etT4D7tv37707du3WvcRERH3YOsksI185ebmkpmZyc0331zLkUl1ObXOXFxcHHFxcXb7Vq1aZfw5NjaW2NjYS65r3rw5q1evrrG41j6wlp82/XTF46M/H83OxVd4/cninTRt05S1g9Ze9njrQa0Z9dmoqz5/4MCB/OlPfyInJ8co0rtx40bGjRsHwOeff867775LQUEBpaWlvPLKK9x9993G9Xv27OGtt95i9erVpKWlGb10bdq0Mc45cuQICxcupKCggOzsbJ544gkeeOAB3nzzTQoKClixYgXh4eF8++23LFmyhB9++IHFixdTXFxMo0aNWLBgAbfccgtjxowhOjqalJQUsrOz+cMf/sB999131fbZnDt3jrlz53L69Gm8vLx49tln6dmzJ7t37zZ6Bxs2bMhrr72Gn58fzzzzjPGvxSlTpijRFBFxgIrJnO3PmZmZtRmSXCenDbO6Mx9/HwqzLq2WDeU9dL4Bvtd1/8DAQPr27WuUXElPT+fYsWN0796dsrIyPvjgA/7yl7+wbt06Hn/8cVauXHnFez333HPMnDmTjz/+mBtvvNHY/+GHHzJ58mTWr1/PP//5T/70pz8RHBzMtGnT6NOnD5MmTTLOLSkp4ZlnnuHFF19k48aNjBw5kmeeecY4bjabWbduHc8//3yVhmUXLlxITEwMSUlJ/OlPf+KFF17g3LlzvP3228yfP58NGzbQtWtX0tLS2Lp1K82bN2fDhg0sXrzYbr6liIhUn4ZZPY9e5wXX7DnLO5OHfxP/yyZ0/k38adK6CfOs864rhqFDh/LGG28wcuRIkpKSGDx4sLFU/M9//jPbt2/nyJEjfP/993h5XT4Hz87OJiMjg27duhn3XL9+PVA+j23nzp288847HDlyxG4l028dP36c4OBg2rVrB5T3HL700kvk5eUB5VXCAVq3bk1OTqI1HKsAACAASURBVE6l2/jNN9+waNEiAG688Ubat2/P/v376du3L0899RSxsbH07duXbt26cfz4cZYtW0Z6ejq9evViypQplX6OiIhcWcWeOVsyp54596aeuUoIaBpAj7k9Lnusx9weBIRe/wqge+65h8zMTM6cOcPGjRsZNmwYUL7qc/jw4Zw8eZK7776bMWPGXPEeJpMJq9VqbFesG/T000+zdetWbrvtNp5++umrxlJWVnbJPqvVisViATBWBle1REzF2Crec/z48axevZqbb76ZpUuXsmLFClq0aMHnn39OXFwce/fuZfjw4ZeNS0REKq+wsJDCwkJ8fX1p0KABAQEBeHt7c+HCBYqLi2s7PKkmJXOV4O3rTfux7em3rB/+Tf7/15808affsn60H9veYeVJHnzwQVasWEHDhg2NiajHjx/HZDIxceJEOnXqxNatW42k6rcaNWpEs2bN+OqrrwD49NNPjWP//ve/mTZtGrGxsfzrX/8CMMq9lJaW2t2nZcuW5OTkcODAAQA2bdpEs2bNjPl81RUTE8NHH30ElK+03bdvH3fddRcjRozg4sWLjB8/nvHjx5OWlsZ7771HQkICAwcOZN68eWRnZ5Ofn39dzxcRqesq9sqZTCa8vLxo0qQJoKFWd6Zh1koKaBJA56c6E/VwFBazBW9fbwJCHVtnbujQofTp04fFixcb+9q0acMdd9zBwIEDgfIhzqsVRVy6dCnPP/88r7/+OnfddZexf+rUqYwaNYp69erRpk0bmjdvzsmTJ2nXrh1vvfUWr776Ki1btgTKa7ctX76chQsXUlhYSMOGDVm+fHmV2jJv3jwWLlxobK9atYq5c+fy0ksvsWHDBsrKyli0aBFhYWE888wz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\n", 800 | "text/plain": [ 801 | "
" 802 | ] 803 | }, 804 | "metadata": {}, 805 | "output_type": "display_data" 806 | } 807 | ], 808 | "source": [ 809 | "plt.figure(figsize=(10, 7))\n", 810 | "ax = plt.subplot()\n", 811 | "sns.set(style='whitegrid', font_scale=1)\n", 812 | "ax.xaxis.set_major_locator(ticker.MultipleLocator(1))\n", 813 | "ax.yaxis.set_major_locator(ticker.MultipleLocator(.02))\n", 814 | "sns.lineplot(epochs, loss_values, label='Training Loss', linewidth=2, marker='o', markersize=8, color='grey')\n", 815 | "sns.lineplot(epochs, val_loss_values, label='Validation Loss', linewidth=2, marker='o', markersize=8, color='purple')\n", 816 | "plt.title('Training + Validation Loss', size=20, weight='bold')\n", 817 | "plt.xlabel('Epochs', size=15, weight='bold')\n", 818 | "plt.ylabel('Loss', size=15, weight='bold')\n", 819 | "plt.axis([0,11,0,.32])\n", 820 | "plt.legend()\n", 821 | "plt.show()\n", 822 | "# plt.savefig('cnn_VGG19_tuned_loss.pdf')" 823 | ] 824 | }, 825 | { 826 | "cell_type": "code", 827 | "execution_count": 37, 828 | "metadata": {}, 829 | "outputs": [ 830 | { 831 | "data": { 832 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnkAAAHFCAYAAACO6e8yAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nOzdeVzU5dr48c/AzADDIjuoYWjmCi65YblgWRKFpam5haZ5POe0+rTYop2y01OeFnqysn6e0vRYmmakx43UMk3NRIUsl1wwN3aQZQaY7fcHzTdGdoEZwOvta17Md5nv3PfMINdc96ayWq1WhBBCCCFEq+Li7AIIIYQQQojGJ0GeEEIIIUQrJEGeEEIIIUQrJEGeEEIIIUQrJEGeEEIIIUQrJEGeEEIIIUQrJEGeEH949tln6dq1a51uDzzwQKM/f0JCgnL9b7/99qqv89RTTynXOXHiRCOW0PFKSkro27evUp+0tLQqz7t8+TI9e/aka9eu9OrVi+Li4no9z/fff688x5tvvqnsnzNnjrL/1KlTtV7n1KlTyvlz5sypVxmutHfvXnbv3m2375ZbbqFr167ccsstDbp2U1izZo1S94iICPLy8pxdJCGueRLkCSGaLXd3d2699VZle+vWrVWe9+2332IymQCIjo7G09PTIeVrChkZGTz22GNMnz6dc+fOObs4dfbVV18p941GIxs2bHBiaYQQAGpnF0CI5uKBBx5g5MiRyva+fftYsWIFALGxsdx1113KMV9f30Z//tGjRxMZGQmg/Lwa06dPJyYmBoB27do1StmcKTY2lv/+979AeZA3e/bsSuds27bN7vzGMmPGDOV9Dw0NbbTr1mTHjh3VBrOvvfYaZWVlaLVah5Slrn7//XeSk5Pt9q1bt474+HgnlUgIARLkCaHo2bMnPXv2VLYLCgqU+506dbILAJvCDTfcwA033NDg60RERBAREdEIJWp8kyZN4uDBgwwePJhly5bV6TFDhw7Fx8eHgoICfvnlF86fP891112nHC8pKVGaNXU6HdHR0Y1W3sjIyAYF3I1t2LBhzi5ClRITE5X7QUFBZGVlcfToUX799Vd69OjhxJIJcW2T5lohGqBiP7rDhw8zceJEIiIiiI6OJj09HYDDhw/z97//nWHDhhEREcGgQYOYNGkS69evr/ZaFfvkDRs2jK5duzJz5kxyc3N54YUXGDx4ML1792batGmkpqbaXaeqPnkmk0nZ9+KLL3L+/Hkee+wxBgwYwE033cTf//73Kvu7nT9/njlz5jBgwAD69evH448/TkZGBpMmTaJr167cfvvtjfyKVqbVau0C7KSkJLvju3fvxmAwAHDrrbfi7u6uHLt48SIvvvgiI0eOpFevXtx0003ExcWxePFiysrKan3umvrk7dq1i4kTJ9K7d29uueUW3njjjRqvefDgQf7617/afQ6mTJnCxo0b7Z7vpZdeUrZfeukl5bMFNffJO3r0KE8//TTDhw9XPoPz5s2r1ORbsd/gxx9/zC+//MLMmTPp27cvgwYNYu7cuWRnZ9f62thYrVYlyPP392fu3LnKsXXr1lX7uMzMTF5++WVuvfVWIiIiGD58OI888ghHjhypdG5hYSFvvfUWo0aNIjIykiFDhjBz5kz27t1rd15171dWVpayf+bMmcr+N998U9mfmprKhAkTiIiIYMSIEWRmZgJ1e99sLBYLn3/+Offddx99+vRhwIAB3HfffXzxxRdYLBYA/v3vfyvPeeUXndLSUqUPamNmpMW1SzJ5QjSSxx9/XAnstFotoaGhHD58mPj4eEpLS5Xz8vPzOXjwIAcPHsRsNjNmzJg6XT8/P5+JEydy9uxZZd++ffuYNm0a27dvx9/fv07XOXfuHOPGjbPrGL99+3Z+/fVXvvnmGzQaDVAeIE2cOJGsrCzlvC1btvDLL7/YBVKOEBsbqwQMW7duZcaMGcqxik21FZvUc3NzmTp1KhcuXFD2lZaWcuLECU6cOMGFCxf45z//eVXl+e9//8tTTz2FbenvkpIS/v3vf7Nz584qz09OTmb69Ol2QWB+fj4HDhzgwIEDmM1mRo8efVVlAdi4cSNz587FaDQq+y5dusSaNWvYvHkzH330Ef3796/0uEOHDvF///d/yudTr9eTmJjI77//zueff16n596/f7/yGsfExHD77bfj6elJcXExGzZs4JlnnqnUvPz7778zefJku89Weno66enp7Ny5k48//piBAwcC5a/TpEmTOH36tHJuVlYWWVlZ/PDDD7z55pvcfffddXylqvfoo48qv7/u7u4EBwfX632zWq08+eSTbNq0STnXYDBw5MgRjhw5wi+//MLLL7/M6NGjefvttzGbzWzZsoXp06cr5+/a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OMErr7xCSEiI+j2TJ0+muLiYK664gvLycvR6PUlJSQOK02638/3336udvb5Ap9OpHce+zptzCQ4OJj4+noiICE+HIoQQTtfe3k5jYyO7du3CYrFgMBiYNGkSY8eOxWg0ejo8cQ7cVuQlJCSwaNEicnNz6erqYtasWYwZM4a8vDzuvPNOLr30UgoKCli4cCFWq5WJEyeyYMECzGYza9asYejQocyePVu9X3FxMfPmzeP+++/n2muvJSQkhMcff3zAcdbX16PRaLjooov6PfXrKW1tbYSFhXk6DKfw1lwURcFisfDDDz8ASKEnhPArNpuNzz//nK1bt6rPWSwWysrKABg/frzPj+gFIrfucNizB15vK1asUL9OT08nPT29z/WYmBi+/PLL095Pr9dTWFjo1BibmpoYMWKEzxR4wj00Gg1Go5HzzjuPY8eOSZEnhPAr7e3t7Ny587TXdu7cSUpKirpUSvgOqWR+xGaz9Wn4EKI3g8FAV1eXp8MQQginstlsWCyW016zWCzqCRjCt0iRdxr+0EkkXEN+NoQQ/igoKAiDwXDaawaDQaZqfZQUeU5gs9lobW2lqamJ1tZWp/3F8+CDD5KdnU1GRgYpKSlkZ2eTnZ3Nm2++6fA9nnrqKbZv337W12RnZw80VNXBgwe56KKL2LJli9PuKYQQwrWMRqN66MCPTZo0SRovfJScOjxA7e3tfP755+zcudPp3UgPPPAAAN9//z25ubkUFxf3+x533XXXT77mXO57Jm+++SbXXHMN69atY/r06U67rxBCCNcJCgpi7NixAKf9fSYjeb5JirwB6OlG6uk+Avd1Iz3zzDN89tlnHD9+nJycHC655BJMJhMdHR20tLSwdOlSpk6dSn5+PuPHj2f8+PH8x3/8BxdccAFfffUVsbGxPPXUU0RFRXHRRRdx4MABnnnmGWpqavj222/54YcfmD17NrfeeitdXV088MADVFRUkJCQgEaj4bbbbuOqq67qE1NXVxclJSWsWbOGOXPm8N1336l7GO7evZvHHnsMRVFISkpi+fLlBAcH8+CDD1JRUUFwcDC33XYbkydP5le/+hWrVq1i6NCh/POf/+TZZ59l9erVzJs3j8jISL7++mv+9re/UVFRQXFxMRaLheDgYJYvX86oUaNO+14333wzt99+O1dffTWKojB9+nRWr14tu7kLIcT/MhqNjB8/npSUFLXIMxqNUuD5MCnyzmLt2rV8/fXXZ7w+d+7cs3YjDR48mLVr1572+gUXXMDvfve7AcVntVrZtGkTbW1tLF26lL/+9a+cf/757Nmzh0ceeUQ9/q3H/v37eeSRR7jkkku44447KCkpYd68eX1ec+DAAdasWUNraytTp05l7ty5aiG1efNmjh07dkqHdI8dO3aQlJTEyJEjmTp1KuvWrePPf/4zVquVP/3pT7z88stcfPHFLF++nLfeeovOzk7a29spLS2loaGB3//+96Smpp4154suuohnn32WEydOUFhYyOrVqwkNDeWpp55izZo1LFmy5LTv9dvf/pbi4mKuvvpqysvLGT58uBR4QgjxI0FBQYSHh3Pw4EG/2EA40EmRNwA6ne6s3Uiu7tIdM2aM+vV//ud/8t5777F582Y+//zz027mHBsbyyWXXAKcLDKbm5tPec1VV11FSEgIsbGxREVF0drayocffkhOTg4ajYbzzjuPiRMnnjaeN998k8zMTAAyMjL405/+xF133cWBAwdISEjg4osvBmDx4sUA3HLLLeTk5KDVaomLi2Pjxo0/uQl1T86DBg1i+fLlbNy4kaNHj7Jz504uvvjiM75Xe3s7JpOJ9vZ23nrrLW644Yazvo8QQgjh66TIO4ufGmlrbW3FYDCcttAzGAzExsaq6+pcITQ0VP36d7/7HVdddRVXXXUVEydO5E9/+tMpr+99fJtGo0FRFIdeExQUhN1uP2ssDQ0N7Ny5ky+++IJVq1ahKAotLS1s3bqV888/v09XamtrK21tbeqxOT2+/fZbIiMjAdTYuru7T5vz8ePHmTdvHv/+7/9OWloagwcP5quvviI4OPi075WYmEhaWhpbtmzho48+cunnIoQQQngD6a4dAG/pRmpububo0aPcddddpKWlsX37dqfuaZSamsqmTZtQFIWamhr27t17ylYixcXFTJgwgQ8++IB3332X9957jz/84Q+8/vrrjBw5koaGBg4dOvT/27v3uKqq9PHjH+6IBN645C1HbcJJIDNSFEUMkdtBBPOaaIZlNeJgpmT1HTM1FRvUl76oRl9p5j0vCAmiw2gK5LVEpshLZmKKCDLigJzjOfv3hz/PKwwRAdlweN5/nXX2Ye3nOaL7ca+91gJg1apVbNy4ES8vL2O/RUVFvPTSS2i1Wlq3bm387P1mBp86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\n", 833 | "text/plain": [ 834 | "
" 835 | ] 836 | }, 837 | "metadata": {}, 838 | "output_type": "display_data" 839 | } 840 | ], 841 | "source": [ 842 | "plt.figure(figsize=(10, 7))\n", 843 | "ax = plt.subplot()\n", 844 | "sns.set(style='whitegrid', font_scale=1)\n", 845 | "ax.xaxis.set_major_locator(ticker.MultipleLocator(1))\n", 846 | "ax.yaxis.set_major_locator(ticker.MultipleLocator(.005))\n", 847 | "sns.lineplot(epochs, acc_values, label='Training Accuracy', linewidth=2, marker='o', markersize=8, color='grey')\n", 848 | "sns.lineplot(epochs, val_acc_values, label='Validation Accuracy', linewidth=2, marker='o', markersize=8, color='purple')\n", 849 | "plt.title('Training + Validation Accuracy', size=20, weight='bold')\n", 850 | "plt.xlabel('Epochs', size=15, weight='bold')\n", 851 | "plt.ylabel('Accuracy', size=15, weight='bold')\n", 852 | "plt.axis([0,11,.91,1])\n", 853 | "plt.legend()\n", 854 | "plt.show()\n", 855 | "# plt.savefig('cnn_VGG19_tuned_accuracy.pdf')" 856 | ] 857 | }, 858 | { 859 | "cell_type": "code", 860 | "execution_count": 35, 861 | "metadata": {}, 862 | "outputs": [ 863 | { 864 | "name": "stdout", 865 | "output_type": "stream", 866 | "text": [ 867 | "Saved model to disk\n" 868 | ] 869 | } 870 | ], 871 | "source": [ 872 | "cnn_3.save(\"cnn_3_tuned.h5\")\n", 873 | "print(\"Saved model to disk\")" 874 | ] 875 | } 876 | ], 877 | "metadata": { 878 | "kernelspec": { 879 | "display_name": "Python 3", 880 | "language": "python", 881 | "name": "python3" 882 | }, 883 | "language_info": { 884 | "codemirror_mode": { 885 | "name": "ipython", 886 | "version": 3 887 | }, 888 | "file_extension": ".py", 889 | "mimetype": "text/x-python", 890 | "name": "python", 891 | "nbconvert_exporter": "python", 892 | "pygments_lexer": "ipython3", 893 | "version": "3.7.4" 894 | }, 895 | "toc": { 896 | "base_numbering": 1, 897 | "nav_menu": {}, 898 | "number_sections": true, 899 | "sideBar": true, 900 | "skip_h1_title": true, 901 | "title_cell": "Table of Contents", 902 | "title_sidebar": "Contents", 903 | "toc_cell": true, 904 | "toc_position": {}, 905 | "toc_section_display": true, 906 | "toc_window_display": false 907 | } 908 | }, 909 | "nbformat": 4, 910 | "nbformat_minor": 2 911 | } 912 | -------------------------------------------------------------------------------- /Project_Prompt/Flatiron Data Science Capstone Project Guidelines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Project_Prompt/Flatiron Data Science Capstone Project Guidelines.pdf -------------------------------------------------------------------------------- /Project_Prompt/Flatiron Data Science Capstone Project Timeline.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Project_Prompt/Flatiron Data Science Capstone Project Timeline.pdf -------------------------------------------------------------------------------- /Py_Files/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Py_Files/__init__.py -------------------------------------------------------------------------------- /Py_Files/image_size_stats.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | 3 | def get_size_statistics(DIR): 4 | heights = [] 5 | widths = [] 6 | for img in os.listdir(DIR): 7 | path = os.path.join(DIR, img) 8 | data = np.array(Image.open(path)) #PIL Image library 9 | heights.append(data.shape[0]) 10 | widths.append(data.shape[1]) 11 | avg_height = sum(heights) / len(heights) 12 | avg_width = sum(widths) / len(widths) 13 | print("Average Height: " + str(avg_height)) 14 | print("Max Height: " + str(max(heights))) 15 | print("Min Height: " + str(min(heights))) 16 | print('\n') 17 | print("Average Width: " + str(avg_width)) 18 | print("Max Width: " + str(max(widths))) 19 | print("Min Width: " + str(min(widths))) -------------------------------------------------------------------------------- /Py_Files/imports.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | sys.path.append("..") 4 | import matplotlib.pyplot as plt 5 | import matplotlib.ticker as ticker 6 | import seaborn as sns 7 | import numpy as np 8 | import pandas as pd 9 | import requests 10 | import json 11 | import math 12 | import sklearn 13 | from scipy import stats 14 | from scipy.stats import norm 15 | from sklearn.utils import resample 16 | import pickle 17 | import statsmodels.api as sm 18 | from statsmodels.formula.api import ols 19 | import scipy.stats as stats 20 | from wordcloud import WordCloud 21 | import random 22 | from collections import Counter 23 | from statsmodels.stats.outliers_influence import variance_inflation_factor 24 | from sklearn.model_selection import train_test_split, GridSearchCV, RandomizedSearchCV, cross_val_score, cross_validate 25 | from sklearn.linear_model import LassoCV, Lasso, Ridge, LinearRegression, LogisticRegression 26 | from sklearn.preprocessing import StandardScaler 27 | from sklearn.linear_model import SGDClassifier 28 | from sklearn.metrics import roc_curve, auc, confusion_matrix, roc_auc_score, precision_recall_curve, precision_recall_fscore_support 29 | import scipy.stats as stats 30 | from sklearn.preprocessing import OneHotEncoder 31 | from sklearn.ensemble import RandomForestClassifier 32 | from imblearn.over_sampling import SMOTE, ADASYN 33 | from pprint import pprint 34 | import keras 35 | from keras.preprocessing import image 36 | from keras.preprocessing.image import ImageDataGenerator 37 | from keras.models import Sequential, load_model, Input, Model 38 | from keras.layers.core import Dense, Dropout, Activation, Flatten 39 | from keras.layers import Conv2D, MaxPooling2D, BatchNormalization 40 | from keras.utils import np_utils 41 | from keras import backend 42 | from PIL import Image 43 | import imageio 44 | import os 45 | -------------------------------------------------------------------------------- /Py_Files/max_range.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | pd.set_option('display.max_rows', 1000) 3 | pd.set_option('display.max_columns', 1000) 4 | pd.set_option('display.width', 1000) 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deficiency Detection 2 | 3 | ![Title-Slide](/Images/Slides/Title-Slide.jpg) 4 | 5 | # 6 | ### Project File Summary 7 | 8 | - [README.md](README.md) - a summary of all contents in this repository. 9 | - [Images](/Images) - Exported plots, etc... 10 | - [Jupyter_Notebooks](/Jupyter_Notebooks) - All Jupyter Notebooks for this project. 11 | - [Py_Files](/Py_Files) - .py files loaded / imported in the Jupyter Notebooks. 12 | - [Final_Presentation](/Final_Presentation) - A non-technical presentation of the project. 13 | - [Web_Application](/Web_Application) - Code + video demo of a simple proof-of-concept web-app that detects cracking. 14 | 15 | # 16 | ### Project Members 17 | 18 | - [Alex Cheng](https://github.com/alexwcheng) 19 | 20 | # 21 | ### Project Scenario 22 | 23 | Architects and engineers visit construction sites regularly to observe general progress and identify **deficient work.** Photography is the primary way to document conditions on-site. If the project is large, then thousands of photos can be taken on a single visit. After the site visit, a field report is made that records general observations and identifies any deficient work. It is very time-consuming to find all of the images that capture deficient work in order to generate a detailed and thorough field report. 24 | 25 | So to make life easier, an automated tool powered by a **Convolutional Neural Network (CNN)** can help detect obviously deficient work for us - in particular, **cracking.** This tool is not intended to replace manual review of construction images completely but would speed up the process significantly. In a large design firm, this tool would save thousands of hours of labor per year. This, in turn, saves hundreds of thousands of dollars, which means more profit and less mind-numbing work to be done by already overworked professionals. 26 | 27 | ![Deficient-Work](/Images/Slides/Deficient-Work.jpg) 28 | 29 | ![Cracking](/Images/Slides/Deficient-Cracking.jpg) 30 | 31 | # 32 | ### Project Goals 33 | 34 | The goal of this project is to create an automated tool that can rapidly classify 3 things about a construction photo: 35 | 36 | 1. Is the photo "general" or "specific"? 37 | 2. What type of material is in the photo? 38 | 3. Is this material "cracked" or "not cracked"? 39 | 40 | ![1](/Images/Slides/1-General-Vs-Specific.jpg) 41 | 42 | ![2](/Images/Slides/2-Material-Type.jpg) 43 | 44 | ![3](/Images/Slides/3-Crack-Classification.jpg) 45 | 46 | # 47 | ### Data 48 | 49 | I gathered a dataset of roughly 4,000 images of general construction progress photos, and photos focusing on common building materials seen on construction sites, including brick, concrete, drywall, glass, and tile. The dataset was built using combination of actual construction photos, web-scraped photos, and personal photography. In building this unique dataset, I tried to keep the dataset balanced in terms of "cracked" versus "not cracked" images. Since people take pictures of construction deficiencies at many different scales, I endeavored to collect a variety of photos with cracks of all sizes. 50 | 51 | One challenge to overcome is to have the crack be large or prominent enough in the photo for a human (or a computer) to detect it. So images of both "obvious" and "subtle" cracking were included in the dataset. Another challenge is "noise" in the photo - like people, or construction tools, or other visual distractions. So a range of images were included that introduce various amounts of visual "noise" to ensure that the CNN would pick up on cracking in both simple and more complex scenes. 52 | 53 | # 54 | ### Evaluation Metrics 55 | 56 | Next, I had to define the evaluation metrics for success. Missing deficiencies is potentially a safety issue. So arguably, the most important metric to evaluate "success" would be to measure **RECALL** and/or **FALSE NEGATIVE RATE.** However, we don't want to just classify all images as "deficient"...because then we wouldn't be saving architects and engineers any time or effort! So **F1-Score** is likely the best metric to measure instead since it balances precision and recall. To explain performance non-technically, I used accuracy since most already have an understanding of this metric. 57 | 58 | # 59 | ### CNN Building + Training 60 | 61 | • I built and trained 3 CNNs: 62 | 63 | • One for "general" vs. "specific" classification. 64 | 65 | • One for material type classification. 66 | 67 | • One for "cracked" vs. "not cracked" classification. 68 | 69 | # 70 | ### CNN Metrics 71 | 72 | I analyzed confusion matrix results of the CNN models, then determined accuracy, precision, recall, and F1 score metrics. Next, I plotted prediction probabilities for each type of classification. Prediction probabiities are important in crack detection. Architects and engineers want to be certain that they are not missing any significant, potentially dangerous deficiencies. Otherwise, there will be a significant professional liability. So I determined a prediction probability "cutoff" point at which an image would need to be manually checked by a person, since the model is not "confident" enough in its prediction for architects and engineers to trust the prediction completely. The decided cutoff was **90% prediction probability.** 73 | 74 | • For "general" versus "specific" classification (2 classes) - the model was able to classify with 90.4% accuracy. 75 | 76 | • For material type classification (5 classes) - the model was able to classfy with 91.2% accuracy. 77 | 78 | • For "cracked" versus "not cracked" classification (2 classes) - the model was able to classify with 81.4% accuracy. 79 | 80 | ![Prediction Probabilities At Each Stage Of Classification](/Images/Prediction_Probabilities/Prediction_Probabilities_Slide.jpg) 81 | 82 | # 83 | ### Conclusions 84 | 85 | • For every 1,000 images: 86 | 87 | • At a 90% prediction probability cutoff, we only have to manually check 140 images. (86% reduction of work.) 88 | 89 | • At a 95% prediction probability cutoff, we only have to manually check 200 images. (80% reduction of work.) 90 | 91 | • At a 99% prediction probability cutoff, we only have to manually check 310 images. (69% reduction of work.) 92 | 93 | Given that the model was only able to correctly identify "cracked" images 2 out of every 3 times, I would hesitate to put this model in production at the moment. Automated deficiency detection potentially poses a safety issue if very serious cracking is missed by the algorithm. So before implementing this tool, it would be prudent to gather a larger set of images and spend more time tweaking the CNN architecture to produce more reliable results. I think the model should be correctly identifying 9 out of every 10 "cracked" images before considering putting the model to use in the real-world. 94 | 95 | Another variable to consider is the prediction probability "cutoff" point. How much uncertainty from the model's decision-making are we willing to tolerate? There is an strong positive correlation between the model's prediction probability cutoff percentage and the number of images to be manually checked. As the prediction probability cutoff increases, so do the number of images to be manually checked. So an important question is this: are we more willing to do more manual checking to ensure the safety of building users? Or, are we willing to miss a few cracks observed on the construction site to save more time and money? This should be debated with other practicing professionals to arrive at a consensus. 96 | 97 | # 98 | ### App Demo 99 | 100 | **Full app demo with narrative on YouTube: https://www.youtube.com/watch?v=rFzwX8IaSnM** 101 | 102 | ![Deficiency-Detection-Demo](Web_Application/Deficiency-Detection-Demo.gif) 103 | 104 | 105 | 106 | # 107 | ### Future Work 108 | 109 | To improve this project, I would use images with even more “visual noise” to train on. Furthermore, I would consider more types of materials, such as plastics, wood, composites, or even rammed earth. Finally, I would spend more time training and tuning various layers of the CNNs to improve training metrics and reduce the loss function. 110 | 111 | In the future, I would build more CNNs to detect other types of deficiencies besides cracking. Then we could combine these models to build a tool that can detect all types of construction deficiencies. In the further future, instead of people, maybe drones could take photos of construction sites! Using a more robust version of this tool, drones could auto-identify deficient work! This would save an even more tremendous amount of time and money for architecture, engineering, and construction firms. 112 | -------------------------------------------------------------------------------- /Web_Application/Deficiency-Detection-Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Web_Application/Deficiency-Detection-Demo.gif -------------------------------------------------------------------------------- /Web_Application/Deficiency-Detection-Demo.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexwcheng/crack-detection/de00819b2110576a38858f664f0b5399cf1e1bad/Web_Application/Deficiency-Detection-Demo.mov -------------------------------------------------------------------------------- /Web_Application/Py_Files/Crack_Testing.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array 4 | from keras.models import Sequential, load_model 5 | import time 6 | from keras import backend as K 7 | 8 | classes = ['Cracked', 'Not Cracked'] 9 | 10 | #Prediction Function 11 | def predict(model, path): 12 | img = load_img(path, target_size=(256, 256)) 13 | img = img_to_array(img) 14 | img = img/255 15 | img = np.expand_dims(img, axis=0) 16 | predict = model.predict(img) 17 | pred_name = classes[np.argmax(predict)] 18 | prediction = str(round(predict.max()*100, 2)) 19 | return prediction + '%', pred_name 20 | 21 | if __name__ == "__predict__": 22 | predict() -------------------------------------------------------------------------------- /Web_Application/Py_Files/General_Testing.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array 4 | from keras.models import Sequential, load_model 5 | import time 6 | from keras import backend as K 7 | 8 | classes = ['General', 'Specific'] 9 | 10 | #Prediction Function 11 | def predict(model, path): 12 | img = load_img(path, target_size=(256, 256)) 13 | img = img_to_array(img) 14 | img = img/255 15 | img = np.expand_dims(img, axis=0) 16 | predict = model.predict(img) 17 | pred_name = classes[np.argmax(predict)] 18 | prediction = str(round(predict.max()*100, 2)) 19 | return prediction + '%', pred_name 20 | 21 | if __name__ == "__predict__": 22 | predict() -------------------------------------------------------------------------------- /Web_Application/Py_Files/Material_Testing.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array 4 | from keras.models import Sequential, load_model 5 | import time 6 | from keras import backend as K 7 | 8 | classes = ['Brick', 'Concrete', 'Drywall', 'General', 'Glass', 'Tile'] 9 | 10 | #Prediction Function 11 | def predict(model, path): 12 | img = load_img(path, target_size=(256, 256)) 13 | img = img_to_array(img) 14 | img = img/255 15 | img = np.expand_dims(img, axis=0) 16 | predict = model.predict(img) 17 | pred_name = classes[np.argmax(predict)] 18 | prediction = str(round(predict.max()*100, 2)) 19 | return prediction + '%', pred_name 20 | 21 | if __name__ == "__predict__": 22 | predict() -------------------------------------------------------------------------------- /Web_Application/Py_Files/deficiency-detection.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import matplotlib.pyplot as plt 3 | import matplotlib.ticker as ticker 4 | import seaborn as sns 5 | import numpy as np 6 | import pandas as pd 7 | import requests 8 | import json 9 | import math 10 | import sklearn 11 | from scipy import stats 12 | from scipy.stats import norm 13 | from sklearn.utils import resample 14 | import pickle 15 | import statsmodels.api as sm 16 | from statsmodels.formula.api import ols 17 | import scipy.stats as stats 18 | from wordcloud import WordCloud 19 | import random 20 | from collections import Counter 21 | from statsmodels.stats.outliers_influence import variance_inflation_factor 22 | from sklearn.model_selection import train_test_split, GridSearchCV, RandomizedSearchCV, cross_val_score, cross_validate 23 | from sklearn.linear_model import LassoCV, Lasso, Ridge, LinearRegression, LogisticRegression 24 | from sklearn.preprocessing import StandardScaler 25 | from sklearn.linear_model import SGDClassifier 26 | from sklearn.metrics import roc_curve, auc, confusion_matrix, roc_auc_score, precision_recall_curve, precision_recall_fscore_support 27 | import scipy.stats as stats 28 | from sklearn.preprocessing import OneHotEncoder 29 | from sklearn.ensemble import RandomForestClassifier 30 | from imblearn.over_sampling import SMOTE, ADASYN 31 | from pprint import pprint 32 | import keras 33 | from keras.preprocessing import image 34 | from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img 35 | from keras.models import Sequential, load_model, Input, Model 36 | from keras.layers.core import Dense, Dropout, Activation, Flatten 37 | from keras.layers import Conv2D, MaxPooling2D, BatchNormalization 38 | from keras.utils import np_utils 39 | from keras import backend, layers, models 40 | from PIL import Image 41 | import imageio 42 | import os 43 | import keras.backend.tensorflow_backend as tb 44 | tb._SYMBOLIC_SCOPE.value = True 45 | 46 | st.title('Deficiency Detection') 47 | st.header("This tool automatically identifies cracking in materials using Convolutional Neural Networks (CNNs).") 48 | st.write("Please pick an image using the drop-down menu on the left.") 49 | 50 | st.sidebar.title("Image Selection") 51 | 52 | from os import listdir 53 | from os.path import isfile, join 54 | onlyfiles = [f for f in listdir("/Users/alexandercheng/Desktop/Demo-Images/") if isfile(join("/Users/alexandercheng/Desktop/Demo-Images/", f))] 55 | imageselect = st.sidebar.selectbox("Please pick an image using this drop-down menu.", onlyfiles) 56 | 57 | image = Image.open("/Users/alexandercheng/Desktop/Demo-Images/" + imageselect) 58 | st.image(image, use_column_width=True) 59 | 60 | import General_Testing 61 | import Material_Testing 62 | import Crack_Testing 63 | 64 | @st.cache 65 | def General_Detection(): 66 | model_1_path = '/Users/alexandercheng/Desktop/Deficiency-Detection-Web-Application/cnn_general.h5' 67 | model_1 = load_model('/Users/alexandercheng/Desktop/Deficiency-Detection-Web-Application/cnn_general.h5') 68 | return model_1 69 | 70 | @st.cache 71 | def Material_Detection(): 72 | model_2_path = '/Users/alexandercheng/Desktop/Deficiency-Detection-Web-Application/cnn_material_classification.h5' 73 | model_2 = load_model('/Users/alexandercheng/Desktop/Deficiency-Detection-Web-Application/cnn_material_classification.h5') 74 | return model_2 75 | 76 | @st.cache 77 | def Crack_Detection(): 78 | model_3_path = '/Users/alexandercheng/Desktop/Deficiency-Detection-Web-Application/cnn_all.h5' 79 | model_3 = load_model('/Users/alexandercheng/Desktop/Deficiency-Detection-Web-Application/cnn_all.h5') 80 | return model_3 81 | 82 | 83 | model_1 = General_Detection() 84 | model_2 = Material_Detection() 85 | model_3 = Crack_Detection() 86 | 87 | prediction_1 = General_Testing.predict((model_1),"/Users/alexandercheng/Desktop/Demo-Images/" + imageselect) 88 | st.subheader('Step 1:') 89 | st.write('Is the image "General" or "Specific" ?') 90 | st.title(prediction_1) 91 | 92 | if prediction_1[1] == 'General': 93 | st.write('**This is just a general progress photo.**') 94 | st.write('**Nothing specific to detect.**') 95 | 96 | elif prediction_1[1] == 'Specific': 97 | 98 | prediction_2 = Material_Testing.predict((model_2),"/Users/alexandercheng/Desktop/Demo-Images/" + imageselect) 99 | st.subheader('Step 2:') 100 | st.write('What is the material type?') 101 | st.title(prediction_2) 102 | 103 | prediction_3 = Crack_Testing.predict((model_3),"/Users/alexandercheng/Desktop/Demo-Images/" + imageselect) 104 | st.subheader('Step 3:') 105 | st.write('Is it "Cracked" Or "Not Cracked" ?') 106 | st.title(prediction_3) 107 | 108 | if float(prediction_3[0][0:3]) < 90: 109 | st.write('**PREDICTION IS LESS THAN 90% PROBABILITY.**') 110 | st.write('**PLEASE REVIEW IMAGE MANUALLY.**') 111 | st.title('😄') 112 | 113 | else: 114 | pass 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | --------------------------------------------------------------------------------