├── .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 | 
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 | 
28 |
29 | 
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 | 
41 |
42 | 
43 |
44 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------