-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimageclassification.py
More file actions
232 lines (158 loc) · 12.8 KB
/
imageclassification.py
File metadata and controls
232 lines (158 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# -*- coding: utf-8 -*-
"""ImageClassification.ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/github/Paimonz/computer-vision/blob/main/ImageClassification.ipynb
"""
#Saiba mais em:
import matplotlib.pyplot as plt #https://matplotlib.org/3.5.3/api/_as_gen/matplotlib.pyplot.html
import numpy as np #https://numpy.org/doc/
import tensorflow as tf #https://www.tensorflow.org/api_docs/python/tf
import tensorflow_hub as hub #https://www.tensorflow.org/hub?hl=pt-br
from keras.preprocessing.image import ImageDataGenerator #https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
print('TensorFlow version:', tf.__version__) #Verifica a versão do TensorFlow.
print('TensorFlow Hub version:', hub.__version__) #Verifica a versão do TensorFlow Hub.
#O TensorFlow Hub tem vários modelos de classificação, você pode verificar outros modelos em:
#https://tfhub.dev/s?module-type=image-feature-vector&tf-version=tf2&q=efficientnet
#Usei o modelo efficientnetv2-b2-21k pois acredito ser mais adequato para os tipos de imagens que tenho.
model_name = 'efficientnetv2-b2-21k'
#Criando uma nova variavel, armazenado o caminho do modelo.
#O primeiro parametro é o nome do modelo e o segundo é o link para donwload do modelo.
models_path = {
"efficientnetv2-b2-21k": "https://tfhub.dev/google/imagenet/efficientnet_v2_imagenet21k_b2/feature_vector/2",
}
#Criando nova variavel para a dimensões das imagens, pois cada modelo trabalha com uma dimensão expecifica.
#Para trabalhar com o modelo escolhido as imagens tem que ser igual ou inferior as dimensões 260x260.
models_pixels = {
"efficientnetv2-b2-21k": 260
}
#Armezenando o caminho do modelo através do nome do nomdelo.
model_path = models_path.get(model_name)
model_path
#Armazenando as dimensões/pixels do modelo atravéz do nome do modelo.
pixels = models_pixels.get(model_name)
pixels
#Criando o formato das imagens.
image_size = (pixels, pixels)
image_size
print('Model: ', model_name) #Para mostrar com qual modelo estamos trabalhando.
print('Path: ', model_path) #Mostrando o caminho/link onde é possível encontrar o modelo.
print('Imagem size: ', image_size) #Revelando o formato das imagens que serão trabalhadas no projeto.
#O dataset foi criado/configurado e armazenado no google driver, para seguir esse modelo vc precisará criar o seu próprio dataset e montar o seu driver.
#Saiba mais em: https://saturncloud.io/blog/how-to-import-files-from-google-drive-to-colab/
#Você pode encontrar as imagens utilizadas nesse projeto em: https://www.kaggle.com/datasets/gunavenkatdoddi/eye-diseases-classification
flow_from_directory = "/content/drive/MyDrive/dataset1" #método da classe ImageDataGenerator que permite ler imagens de um grande array numpy e pastas contendo imagens.
data_directory = flow_from_directory #Armazena o caminho do flow_from_directory em data_directory.
print(data_directory) #Mostra o caminho do data_directory.
train_dataset = tf.keras.preprocessing.image_dataset_from_directory(data_directory, #Pegando as imagens que estão no data_directory para o treino
validation_split= .20, #Usaremos 20% do dataset para validação.
subset = 'training', #Significa que essa parte do conjunto de dados é o treinamento.
label_mode='categorical', #Etiqueta do nosso modelo será por categoria, Normal, Cataract, Glaucoma ou Retina_Disease.
seed = 123, #Toda vez que a função for chamada será composta pelas mesmas imagens.
image_size=image_size, #Configura o formato das imagens.
batch_size=1) #Número de amostras processadas antes do modelo ser atualizado.
#Mostra o nome das classes que temos no nosso treinamento
train_dataset.class_names
#Criando uma variavel com os nomes das classes do nosso dataset
classes = train_dataset.class_names
classes
#A função da cardinality retorna o número de elementos em uma lista, no caso irá retorno o número de arquivos usados no treinameno (train_dataset).
training_size = train_dataset.cardinality().numpy()
training_size
#Organizando o dataset em 52 lotes, onde cada lote terá (840/16 = 52,5) 16 imagens.
BATCH_SIZE = 16 #Significa que existem 16 instâncias de treinamento em cada lote.
train_dataset = train_dataset.unbatch().batch(BATCH_SIZE) #Atualizando o batch_size porque inicialmente começamos com batch_size =1
train_dataset
840/16
# https://www.tensorflow.org/api_docs/python/tf/repeat
# https://stackoverflow.com/questions/53514495/what-does-batch-repeat-and-shuffle-do-with-tensorflow-dataset
train_dataset = train_dataset.repeat()
#Image augmentation: https://www.tensorflow.org/tutorials/images/data_augmentation
#from multiprocessing.process import parent_process
normalization_layer = tf.keras.layers.Rescaling(1. /255) #Normalization = transformação de dados que alinha os valores dos dados a uma escala comum. Rescaling = reduzindo a escala (pixels) das imagens de 0-255 para 0-1.
pre_processing = tf.keras.Sequential([normalization_layer]) #Sequential = irá criar a estrutura da rede neural, que será passado uma sequencia de camadas por isso usaremos sequential.
pre_processing.add(tf.keras.layers.RandomRotation(40)) #Irá girar algumas imagens aleatório em 40° e adicionar no pré-processamento, pois pode ser que as imagens separadas para o treinamento não sejam o suficienteentão será necessário "criar" mais imagens para o mesmo.
pre_processing.add(tf.keras.layers.RandomTranslation(0, 0.2)) #O segundo parametro é a largura, irá deslocar as imagens aleatóriamente em 20% na horizontal.
pre_processing.add(tf.keras.layers.RandomTranslation(0.2, 0)) #O primeiro parametro é a altura, irá deslocar as imagens aleatóriamente em 20% na vertical.
pre_processing.add(tf.keras.layers.RandomZoom(0.2, 0.2)) #Adicionando imagens aleatórias com o zoom aumentando em 20% e com o zoom reduzido em 20%.
pre_processing.add(tf.keras.layers.RandomFlip(mode = 'horizontal')) #Gira as imagens horizontalmente.
#MAP em Python é uma função que funciona como um iterador para retornar um resultado após aplicar uma função a cada item de um iterável (tupla, listas, etc.). É usado quando
#você deseja aplicar uma única função de transformação a todos os elementos iteráveis. O iterável e a função são passados como argumentos para o mapa em Python.
#As funções LAMBDA são semelhantes às funções definidas pelo usuário, mas sem nome. Eles são comumente chamados de funções anônimas. As funções lambda são eficientes sempre que
#você deseja criar uma função que contenha apenas expressões simples – ou seja, expressões que geralmente são uma única linha de uma instrução.
train_dataset = train_dataset.map(lambda images, labels: (pre_processing(images), labels)) #Irá mandar as imagens para o pre_processing.
train_dataset
test_dataset = tf.keras.preprocessing.image_dataset_from_directory(data_directory,
validation_split= .20,
subset ='validation', #Agora o nome do subconjunto será validation, que usaremos para o teste.
label_mode ='categorical',
seed = 123,
image_size = image_size,
batch_size = 1)
test_size = test_dataset.cardinality().numpy() #Extrai a quantidade de imagens que será utilizada para o teste
test_size #Mostra a quantidade de imagens que iremos utilizar para o teste
#Será necessário alterar o conjunto de dados para o mesmo formado utilizado no treinamento.
test_dataset = test_dataset.unbatch().batch(BATCH_SIZE)
test_dataset = test_dataset.map(lambda images, labels: (pre_processing(images), labels))
model = tf.keras.Sequential([ #Uma rede neural é composta por uma sequencia de camadas.
tf.keras.layers.InputLayer(input_shape= image_size + (3,)), #Entrada da imagens, o número 3 é devido a imagen ser colorida RGB
hub.KerasLayer(model_path, trainable = False), #Fazer o download do modelo, "trainable = False" isso significa que quando treinarmos a rede neural, não vamos treinar esses pesos que já estão armazenado no modelo do qual faremos o download.
tf.keras.layers.Dropout(rate = 0.2), #Dropout: https://jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf
tf.keras.layers.Dense(len(classes)) #O quantidade de neurônios de sáida deverá ser a mesma quntidade de de classes
])
(None, ) + image_size + (3, )
model.build((None, )+ image_size + (3,)) #O primeiro parametro siginifica a quantidade de imagens que será enviada para o modelo, por isso começa "vazia".
model.summary()
#Adam = O algoritmo Adaptive Movement Estimation, ou Adam, para abreviar, é uma extensão da descida gradiente e um sucessor natural de técnicas como AdaGrad e RMSProp que adapta
#automaticamente uma taxa de aprendizagem para cada variável de entrada para a função objetivo e suaviza ainda mais o processo de pesquisa usando um exponencialmente.
model.compile(optimizer='adam', loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True), metrics = 'accuracy')
steps_per_epoch = training_size // BATCH_SIZE
validation_steps = test_size // BATCH_SIZE
print(steps_per_epoch, validation_steps)
#"model.fir" a rede neural começará a treinar, os pesos serão ajustados e vamos enviar o treino.
#Epochs = Uma época é quando todos os dados de treinamento são usados de uma vez e é definida como o número total de iterações de todos os dados de treinamento em um ciclo para treinar o modelo de aprendizado de máquina
hist = model.fit(train_dataset, epochs= 15, steps_per_epoch = steps_per_epoch,
validation_data = test_dataset, validation_steps = validation_steps).history
plt.figure() #O gráfico é interessante pois assim você consegue saber por quantas épocas será necessário treinar o modelo.
plt.ylabel('Loss (training and validation)')
plt.xlabel('Steps')
plt.plot(hist['loss'], label = 'training')
plt.plot(hist['val_loss'], label = 'testing')
plt.legend();
plt.figure()
plt.ylabel('Accuracy (training and validation)')
plt.xlabel('Steps')
plt.plot(hist['accuracy'], label = 'training')
plt.plot(hist['val_accuracy'], label = 'testing')
plt.legend();
#Criando duas variáveis, x e y: x = será o pixels da imagens e y = será o rotulo/etiqueta.
#Precisamos usar a função "Next" para obter a próxima imagem.
#iter é um parâmetro da função, é o iterador sobre o qual a iteração deve ser realizada.
#O segundo paramêtro da função "test_dataset" será o valor padrão a ser impresso se chegarmos ao final do iterador.
x, y = next(iter(test_dataset))
#As informações abaixo são referente aos pixels das imagens
x
#Em cada lote tem 16 imagens, de 260x260 pixels coloridas(RGB).
x.shape
#as linhas são referente as imagens no lote e as colunas são referente as classes.
y
#Em cada lote tem 16 imagens com duas classes possíevis.
y.shape
#Para classificar a imagem, o 1° parametro é a possição da imagem, 2° e 3° são os pixels e o 4° é referente ao canal de cores.
image = x[0, :, :, :]
image
y_true = y[2] #Selecionando a imagem que está na posição 3
y_true
y_true = np.argmax(y[2]) #np.argmax irá retonar a posição do maior valor no conjunto de array.
y_true
classes[1] #a classe referente a posição 1 é a Catarata.
plt.imshow(image)
plt.axis('off');
image.shape #Formato da imagem 1° e 2° = dimensão da imagem e 3° canal de cores.
image = np.expand_dims(image, axis = 0) #Para enviar para a rede neural, precisamos converter esse formato para o formato em lote.
image.shape
prediction = model.predict(image)
prediction
prediction = np.argmax(prediction) #Fazendo a classificação da imagem
prediction
classes[2]