1
+ import tensorflow as tf
2
+ import tensorflow_hub as hub
3
+ from tensorflow .keras import layers
4
+
5
+ import matplotlib .pyplot as plt
6
+ import matplotlib .image as mpimg # To view image
7
+ import numpy as np
8
+ import datetime
9
+ import random
10
+ import os
11
+
12
+ def print_tf_version ():
13
+ """
14
+ Prints current TensorFlow version
15
+ To check whether you are using TF2
16
+ """
17
+ v = tf .__version__
18
+ if v [0 ] == '2' :
19
+ print ("Apropriate version!" )
20
+ print ("Your version is: " , v )
21
+
22
+ ##############################################
23
+ ### 03. Classification ######################
24
+ ##############################################
25
+
26
+ def plot_2D_dots_predictions (train_data ,
27
+ test_data ,
28
+ train_labels ,
29
+ test_labels ,
30
+ predictions ):
31
+ """
32
+ Plots training data, test data and compares predictions.
33
+ """
34
+ plt .figure (figsize = (10 , 7 ))
35
+ plt .scatter (train_data , train_labels , c = "b" , label = "Training data" )
36
+ plt .scatter (test_data , test_labels , c = "g" , label = "Testing data" )
37
+ plt .scatter (test_data , predictions , c = "r" , label = "Predictions" )
38
+ plt .legend ()
39
+
40
+
41
+ def plot_2D_decision_boundary (model , X , y ):
42
+ """
43
+ Plots the decision boundary created by a model predicting on X.
44
+ This function has been adapted from two phenomenal resources:
45
+ 1. CS231n - https://cs231n.github.io/neural-networks-case-study/
46
+ 2. Made with ML basics - https://github.com/GokuMohandas/MadeWithML/blob/main/notebooks/08_Neural_Networks.ipynb
47
+ """
48
+ # Define the axis boundaries of the plot and create a meshgrid
49
+ x_min , x_max = X [:, 0 ].min () - 0.1 , X [:, 0 ].max () + 0.1
50
+ y_min , y_max = X [:, 1 ].min () - 0.1 , X [:, 1 ].max () + 0.1
51
+ xx , yy = np .meshgrid (np .linspace (x_min , x_max , 100 ),
52
+ np .linspace (y_min , y_max , 100 ))
53
+
54
+ # Create X values (we're going to predict on all of these)
55
+ x_in = np .c_ [xx .ravel (), yy .ravel ()] # stack 2D arrays together: https://numpy.org/devdocs/reference/generated/numpy.c_.html
56
+
57
+ # Make predictions using the trained model
58
+ y_pred = model .predict (x_in )
59
+
60
+ # Check for multi-class
61
+ if len (y_pred [0 ]) > 1 :
62
+ print ("doing multiclass classification..." )
63
+ # We have to reshape our predictions to get them ready for plotting
64
+ y_pred = np .argmax (y_pred , axis = 1 ).reshape (xx .shape )
65
+ else :
66
+ print ("doing binary classifcation..." )
67
+ y_pred = np .round (y_pred ).reshape (xx .shape )
68
+
69
+ # Plot decision boundary
70
+ plt .contourf (xx , yy , y_pred , cmap = plt .cm .RdYlBu , alpha = 0.7 )
71
+ plt .scatter (X [:, 0 ], X [:, 1 ], c = y , s = 40 , cmap = plt .cm .RdYlBu )
72
+ plt .xlim (xx .min (), xx .max ())
73
+ plt .ylim (yy .min (), yy .max ())
74
+
75
+ ##############################################
76
+ ### 04. Computer Vision #####################
77
+ ##############################################
78
+
79
+ def check_files_and_directories (folder_path = "pizza_steak" ):
80
+ """
81
+ Walks through all folders inside the `folder_path`
82
+ and prints number of files it found
83
+
84
+ Use it to ivestigate how many training / testing
85
+ examples you have in dataset
86
+ """
87
+ for root , dirs , files in os .walk (folder_path ):
88
+ print (f"There are #{ len (dirs )} directories and #{ len (files )} files In the directory { root } " )
89
+
90
+ def view_random_image_from_dataset (target_dir , target_class ):
91
+ """
92
+ Prints a random image with a given class from a dataset.
93
+ It is assumed that `target_dir` will contain folders for each class,
94
+ where `target_class` is one of the name
95
+ """
96
+
97
+ # Setup target directory (we'll view images from here)
98
+ target_folder = target_dir + target_class
99
+
100
+ # Get a random image path
101
+ random_image = random .sample (os .listdir (target_folder ), 1 )
102
+
103
+ # Read in the image and plot it using matplotlib
104
+ img = mpimg .imread (target_folder + "/" + random_image [0 ])
105
+ plt .imshow (img )
106
+ plt .title (target_class )
107
+ plt .axis ("off" )
108
+
109
+ print (f"Image shape: { img .shape } " ) # show the shape of the image
110
+
111
+ return img
112
+
113
+ def load_scale_and_reshape_image (img_path , img_size = 224 ):
114
+ """
115
+ The function takes a path to an image and returns an image in a
116
+ Tensor format with proper scaling and reshaped for a model
117
+ """
118
+ # Load an image
119
+ img = tf .io .read_file (img_path )
120
+ # Decode an image to tensor and ensure 3 channels
121
+ img = tf .image .decode_image (img , channels = 3 )
122
+ # Resize an image
123
+ img = tf .image .resize (img , size = [img_size , img_size ])
124
+ # Scale an image
125
+ img = img / 255.
126
+
127
+ return img
128
+
129
+ def plot_loss_curves_train_validation (my_history ):
130
+ """
131
+ Plots separate loss curves figures for training and validation metrics
132
+ """
133
+ loss = my_history .history ["loss" ]
134
+ accuracy = my_history .history ["accuracy" ]
135
+ val_loss = my_history .history ["val_loss" ]
136
+ val_accuracy = my_history .history ["val_accuracy" ]
137
+
138
+ epochs = range (len (loss )) # Length of any training metric gives the number of epochs
139
+
140
+ # Plot Loss
141
+ plt .figure (figsize = (20 ,7 ))
142
+ plt .subplot (1 ,2 ,1 )
143
+ plt .plot (epochs , loss , label = "Training Loss" )
144
+ plt .plot (epochs , val_loss , label = "Validation Loss" )
145
+ plt .title ("Loss" )
146
+ plt .xlabel ("epochs" )
147
+ plt .legend ()
148
+
149
+ # Plot Accuracy
150
+ plt .subplot (1 ,2 ,2 )
151
+ plt .plot (epochs , accuracy , label = "Training Accuracy" )
152
+ plt .plot (epochs , val_accuracy , label = "Validation Accuracy" )
153
+ plt .title ("Accuracy" )
154
+ plt .xlabel ("epochs" )
155
+ plt .legend ()
156
+ plt .show ()
157
+
158
+ def binary_predict_and_plot (model , img_path , class_names ):
159
+ """
160
+ It loads an image, makes preprocessing
161
+ Using a model makes a prediction of a class of a model
162
+ And plots an image with assigned class and
163
+ Probability of it for a binary classification
164
+ """
165
+ img = load_scale_and_reshape_image (img_path )
166
+ img_pass = tf .expand_dims (img , axis = 0 )
167
+ probability = model .predict (img_pass )
168
+ pred_class = class_names [int (tf .round (probability ))]
169
+ if probability < 0.5 :
170
+ probability = 1 - probability
171
+ plt .figure ()
172
+ plt .imshow (img )
173
+ plt .title (pred_class + " " + "{:.1f}" .format (100 * probability [0 ][0 ]) + "%" )
174
+ plt .axis (False )
175
+
176
+ ##############################################
177
+ ### 05. Transfer Learning: feature extraction
178
+ ##############################################
179
+
180
+ def view_random_image (data_type = None , classes = None , n_train = 75 , n_test = 250 ):
181
+ """
182
+ The function views random image from a given set of classes and set of datatypes
183
+ Names of `classes` and `data_type` must be the same as in folders tree
184
+
185
+ :param data_type: list of parents folder of classes. Use `None` to apply the value by default [\" train\" , \" test\" ].
186
+ :param classes: list of folders representing classes in dataset. Looks like: [\" hamburger\" , \" pizza\" , ..., \" grilled_salmon\" ]
187
+ :param N_train: number of one class examples in Training folder
188
+ :param N_test: number of one class examples in Testing folder
189
+ """
190
+
191
+ option_type = data_type
192
+ if data_type is None :
193
+ option_type = ["train" , "test" ]
194
+
195
+ option_class = classes
196
+ if classes is None :
197
+ option_class = ["hamburger" , "pizza" , "ice_cream" , "ramen" , "chicken_curry" ,
198
+ "steak" , "chicken_wings" , "sushi" , "fried_rice" , "grilled_salmon" ]
199
+
200
+ chose_type = random .choice (option_type )
201
+ chose_class = random .choice (option_class )
202
+ n_images = n_test - 1
203
+ if chose_type == "train" : n_images = n_train - 1
204
+ chose_image_n = random .randint (0 , n_images )
205
+
206
+ path = "10_food_classes_10_percent/" + chose_type + "/" + chose_class
207
+ images_file = os .listdir (path )
208
+ random_image_file = images_file [chose_image_n ]
209
+
210
+ img = mpimg .imread (path + "/" + random_image_file )
211
+ plt .imshow (img )
212
+ plt .title (chose_class )
213
+ plt .axis ("off" )
214
+ plt .show ()
215
+
216
+ print (f"Image shape: { img .shape } " ) # show the shape of the image
217
+
218
+
219
+ def create_tensorboard_callback (dir_name : str , experiment_name : str ):
220
+ """
221
+ Creates a callback to save training logs into TensorBoard
222
+
223
+ :param dir_name: path or name of a folder to save logs
224
+ :param experiment_name: name of the folder for a current model training to be saved separately in the Log folder
225
+ """
226
+ log_dir = dir_name + "/" + experiment_name + "/" + datetime .datetime .now ().strftime ("%Y%m%d-%H%M%S" )
227
+ tensorboard_callback = tf .keras .callbacks .TensorBoard (log_dir = log_dir )
228
+ print (f"Saving TensorBoard log files to: { log_dir } " )
229
+ return tensorboard_callback
230
+
231
+ def create_feature_extracting_classifier_model (model_url : str , n_units : int , n_classes : int , input_shape ):
232
+ """
233
+ Takes a TensorFlow Hub URL and creates a Keras Sequential model with it.
234
+
235
+ :param model_url: A TensorFlow Hub feature extraction URL.
236
+ This extractor is added as first layers of the model
237
+ :param n_units: Number of hidden neurons after feature extractor.
238
+ :param n_classes: Number of output neurons, should be equal to number of target classes.
239
+
240
+ Returns:
241
+ An uncompiled Keras Sequential model with model_url as feature
242
+ extractor layer and Dense output layer with num_classes outputs.
243
+ """
244
+ # Transfer feature extractor
245
+ feature_extraction = hub .KerasLayer (model_url , # Specify the model
246
+ trainable = False , # Freeze trained patterns
247
+ input_shape = input_shape , # Set correct input shape
248
+ name = "Feature_Extractor" )
249
+ # Create a model
250
+ model = tf .keras .Sequential ([
251
+ feature_extraction ,
252
+ layers .Dense (n_units , activation = "relu" ),
253
+ layers .Dense (n_classes , activation = "sigmoid" )
254
+ ])
255
+
256
+ return model
0 commit comments