Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
inovisao
pynovisao
Commits
1c65b326
Commit
1c65b326
authored
Nov 29, 2017
by
Gabriel Kirsten
Browse files
Commit parcial das funcionalidades de classificação com keras
parent
8bba4c04
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
163 additions
and
51 deletions
+163
-51
src/classification/__init__.py
src/classification/__init__.py
+5
-1
src/classification/classifier.py
src/classification/classifier.py
+6
-1
src/classification/cnn_keras.py
src/classification/cnn_keras.py
+152
-49
No files found.
src/classification/__init__.py
View file @
1c65b326
...
...
@@ -13,9 +13,12 @@ except:
try
:
from
.cnn_keras
import
CNNKeras
except
:
except
Exception
as
e
:
CNNKeras
=
None
print
e
.
message
__all__
=
[
"cnn_caffe"
,
"cnn_keras"
,
"classifier"
,
"weka_classifiers"
]
...
...
@@ -38,4 +41,5 @@ def get_classifier_config():
def
set_classifier_config
(
configs
):
_classifier_list
[
"cnn_caffe"
]
=
Config
.
nvl_config
(
configs
[
"cnn_caffe"
],
_classifier_list
[
"cnn_caffe"
])
_classifier_list
[
"weka_classifiers"
]
=
Config
.
nvl_config
(
configs
[
"weka_classifiers"
],
_classifier_list
[
"weka_classifiers"
])
_classifier_list
[
"cnn_keras"
]
=
Config
.
nvl_config
(
configs
[
"cnn_keras"
],
_classifier_list
[
"cnn_keras"
])
_classifier_list
[
"weka_classifiers"
]
=
Config
.
nvl_config
(
configs
[
"weka_classifiers"
],
_classifier_list
[
"weka_classifiers"
])
\ No newline at end of file
src/classification/classifier.py
View file @
1c65b326
...
...
@@ -78,7 +78,12 @@ class Classifier(object):
"""Return if classifier must be trained.
"""
return
False
def
must_extract_features
(
self
):
"""Return if classifier must be extracted features.
"""
return
True
def
train
(
self
,
dataset
,
training_data
,
force
=
False
):
"""Perform the training of classifier.
"""
...
...
src/classification/cnn_keras.py
View file @
1c65b326
...
...
@@ -4,6 +4,7 @@
"""
Generic classifier with multiple models
Models -> (Xception, VGG16, VGG19, ResNet50, InceptionV3, MobileNet)
Name: cnn_keras.py
Author: Gabriel Kirsten Menezes (gabriel.kirsten@hotmail.com)
...
...
@@ -11,13 +12,14 @@
import
time
import
os
import
numpy
as
np
from
PIL
import
Image
from
keras
import
applications
from
keras.preprocessing.image
import
ImageDataGenerator
from
keras
import
optimizers
from
keras.models
import
Model
from
keras.layers
import
Dropout
,
Flatten
,
Dense
from
keras.callbacks
import
ModelCheckpoint
from
sklearn.metrics
import
confusion_matrix
from
classifier
import
Classifier
...
...
@@ -35,16 +37,25 @@ START_TIME = time.time()
# =========================================================
IMG_WIDTH
,
IMG_HEIGHT
=
256
,
256
TRAIN_DATA_DIR
=
"../data/train"
VALIDATION_DATA_DIR
=
"../data/validation"
BATCH_SIZE
=
16
EPOCHS
=
50
EPOCHS
=
1
CLASS_NAMES
=
[
'ferrugemAsiatica'
,
'folhaSaudavel'
,
'fundo'
,
'manchaAlvo'
,
'mildio'
,
'oidio'
]
class
CNNKeras
(
Classifier
):
""" Class for CNN classifiers based on Keras applications """
def
__init__
(
self
,
architecture
=
"VGG16"
,
fine_tuning_rate
=
100
):
"""
Constructor of CNNKeras
"""
self
.
architecture
=
Config
(
"architecture"
,
architecture
,
str
)
self
.
fine_tuning_rate
=
Config
(
"fineTuningRate"
,
fine_tuning_rate
,
int
)
self
.
file_name
=
"kerasCNN"
def
__init__
(
self
):
model
=
applications
.
VGG16
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
...
...
@@ -60,92 +71,184 @@ class CNNKeras(Classifier):
predictions
=
Dense
(
6
,
activation
=
"softmax"
)(
new_custom_layers
)
# creating the final model
model_fina
l
=
Model
(
inputs
=
model
.
input
,
outputs
=
predictions
)
self
.
mode
l
=
Model
(
inputs
=
model
.
input
,
outputs
=
predictions
)
# compile the model
model_fina
l
.
compile
(
loss
=
"categorical_crossentropy"
,
optimizer
=
optimizers
.
SGD
(
lr
=
0.0001
,
momentum
=
0.9
),
metrics
=
[
"accuracy"
])
self
.
mode
l
.
compile
(
loss
=
"categorical_crossentropy"
,
optimizer
=
optimizers
.
SGD
(
lr
=
0.0001
,
momentum
=
0.9
),
metrics
=
[
"accuracy"
])
def
get_config
(
self
):
"""Return configuration of classifier.
Returns
-------
config : OrderedDict
Current configs of classifier.
"""
pass
keras_config
=
OrderedDict
()
keras_config
[
"architecture"
]
=
self
.
architecture
keras_config
[
"fine_tuning_rate"
]
=
self
.
fine_tuning_rate
return
keras_config
def
set_config
(
self
,
configs
):
"""Update configuration of classifier.
Parameters
----------
configs : OrderedDict
New configs of classifier.
"""
pass
keras_config
=
OrderedDict
()
keras_config
[
"architecture"
]
=
Config
.
nvl_config
(
configs
[
"architecture"
],
self
.
architecture
)
keras_config
[
"fine_tuning_rate"
]
=
Config
.
nvl_config
(
configs
[
"fine_tuning_rate"
],
self
.
fine_tuning_rate
)
def
get_summary_config
(
self
):
"""Return fomatted summary of configuration.
Returns
-------
summary : string
Formatted string with summary of configuration.
"""
pass
keras_config
=
OrderedDict
()
keras_config
[
self
.
architecture
.
label
]
=
self
.
architecture
.
value
keras_config
[
self
.
fine_tuning_rate
.
label
]
=
self
.
fine_tuning_rate
.
value
summary
=
''
for
config
in
keras_config
:
summary
+=
"%s: %s
\n
"
%
(
config
,
str
(
keras_config
[
config
]))
return
summary
def
classify
(
self
,
dataset
,
test_dir
,
test_data
):
pass
""""Perform the classification.
def
train
(
self
,
model_final
):
# Initiate the train and test generators with data Augumentation
train_datagen
=
ImageDataGenerator
(
rescale
=
1.
/
255
,
horizontal_flip
=
True
,
fill_mode
=
"nearest"
,
zoom_range
=
0.3
,
width_shift_range
=
0.3
,
height_shift_range
=
0.3
,
rotation_range
=
30
)
Parameters
----------
dataset : string
Path to image dataset.
test_dir : string
Not used.
test_data : string
Name of test data file.
train_generator
=
train_datagen
.
flow_from_directory
(
TRAIN_DATA_DIR
,
Returns
-------
summary : list of string
List of predicted classes for each instance in test data in ordered way.
"""
predict_directory
=
File
.
make_path
(
dataset
,
test_dir
)
for
root
,
dirs
,
files
in
os
.
walk
(
predict_directory
,
topdown
=
False
):
for
name
in
files
:
print
(
os
.
path
.
join
(
root
,
name
))
if
os
.
path
.
splitext
(
os
.
path
.
join
(
root
,
name
))[
1
].
lower
()
==
".tif"
:
if
os
.
path
.
isfile
(
os
.
path
.
splitext
(
os
.
path
.
join
(
root
,
name
))[
0
]
+
".png"
):
print
"A jpeg file already exists for %s"
%
name
# If a jpeg is *NOT* present, create one from the tiff.
else
:
outfile
=
os
.
path
.
splitext
(
os
.
path
.
join
(
root
,
name
))[
0
]
+
".png"
try
:
im
=
Image
.
open
(
os
.
path
.
join
(
root
,
name
))
print
"Generating jpeg for %s"
%
name
im
.
thumbnail
(
im
.
size
)
im
.
save
(
outfile
,
"PNG"
,
quality
=
100
)
except
Exception
,
e
:
print
e
classify_datagen
=
ImageDataGenerator
()
classify_generator
=
classify_datagen
.
flow_from_directory
(
predict_directory
,
target_size
=
(
IMG_HEIGHT
,
IMG_WIDTH
),
batch_size
=
BATCH_SIZE
,
shuffle
=
True
,
class_mode
=
"categorical"
)
shuffle
=
False
,
class_mode
=
None
)
output_classification
=
self
.
model
.
predict_generator
(
classify_generator
,
classify_generator
.
samples
,
verbose
=
1
)
one_hot_output
=
np
.
argmax
(
output_classification
,
axis
=
1
)
for
index
in
range
(
0
,
len
(
one_hot_output
)):
one_hot_output
[
index
]
=
CLASS_NAMES
[
one_hot_output
[
index
]]
return
one_hot_output
def
train
(
self
,
dataset
,
training_data
,
force
=
False
):
"""Perform the training of classifier.
Parameters
----------
dataset : string
Path to image dataset.
training_data : string
Name of ARFF training file.
force : boolean, optional, default = False
If False don't perform new training if there is trained data.
"""
test_datagen
=
ImageDataGenerator
(
rescale
=
1.
/
255
,
horizontal_flip
=
True
,
fill_mode
=
"nearest"
,
zoom_range
=
0.3
,
width_shift_range
=
0.3
,
height_shift_range
=
0.3
,
rotation_range
=
30
)
validation_generator
=
test_datagen
.
flow_from_directory
(
VALIDATION_DATA_DIR
,
train_datagen
=
ImageDataGenerator
()
train_generator
=
train_datagen
.
flow_from_directory
(
dataset
,
target_size
=
(
IMG_HEIGHT
,
IMG_WIDTH
),
batch_size
=
BATCH_SIZE
,
shuffle
=
True
,
class_mode
=
"categorical"
)
# test_datagen = ImageDataGenerator(
# rescale=1. / 255,
# horizontal_flip=True,
# fill_mode="nearest",
# zoom_range=0.3,
# width_shift_range=0.3,
# height_shift_range=0.3,
# rotation_range=30)
# validation_generator = test_datagen.flow_from_directory(
# VALIDATION_DATA_DIR,
# target_size=(IMG_HEIGHT, IMG_WIDTH),
# batch_size=BATCH_SIZE,
# shuffle=True,
# class_mode="categorical")
# Save the model according to the conditions
checkpoint
=
ModelCheckpoint
(
"../models_checkpoints/"
+
file_name
+
".h5"
,
monitor
=
'val_acc'
,
verbose
=
1
,
save_best_only
=
True
,
save_weights_only
=
False
,
mode
=
'auto'
,
period
=
1
)
checkpoint
=
ModelCheckpoint
(
"../models_checkpoints/"
+
self
.
file_name
+
".h5"
,
monitor
=
'val_acc'
,
verbose
=
1
,
save_best_only
=
True
,
save_weights_only
=
False
,
mode
=
'auto'
,
period
=
1
)
# Train the model
model_fina
l
.
fit_generator
(
self
.
mode
l
.
fit_generator
(
train_generator
,
steps_per_epoch
=
train_generator
.
samples
//
BATCH_SIZE
,
epochs
=
EPOCHS
,
callbacks
=
[
checkpoint
],
validation_data
=
validation_generator
,
validation_steps
=
validation_generator
.
samples
//
BATCH_SIZE
)
callbacks
=
[
checkpoint
])
def
must_train
(
self
):
"""Return if classifier must be trained.
Returns
-------
True
"""
return
True
def
must_extract_features
(
self
):
"""Return if classifier must be extracted features.
Returns
-------
False
"""
return
False
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment