[PYTHON] For those who want to start machine learning with TensorFlow2

Introduction

Currently, I am an M2 major in CS. I usually write mainly machine learning code in PyTorch. It's easy to write for the time being. PyTorch is said to be ** "Define by Run" **, and what is good is that the calculation graph and the timing of data flow are simultaneous, and it is easy to debug because you can check the calculation result in the middle. I'm such a PyTorch believer, but this time I needed to write code in TensorFlow, so I'll leave it as a memo so that I don't forget the know-how at that time.

Before I touched PyTorch, I was able to understand it because I was touching TensorFlow and keras, but I couldn't grasp the contents after becoming TensorFlow2, so it was a good study this time. By the way, TensorFlow1 (TF1) adopted the method of flowing data to the place where the static graph was created by the method called ** "Define and Run" , but in TensorFlow2 (TF2) ** " It uses the same method as Define by Run " and PyTorch.

Who is the target of this article

This article is for those who want to get started with machine learning with TensorFlow2. Looking at other people's articles, there are many articles about TensorFlow1 and I could not find many articles about TensorFlow2 (TF2), so I hope that it will be helpful for those who are thinking of touching TF2 from now on. Also, rather than the sklearn-like method of learning with model.fit etc., I mainly wrote the expert method in the TensorFlow tutorial, so I hope that those who are interested can read it.

Rough content

** 1. TensorFlow Basics ** ** 2. Easy model building and learning with keras (Beginner Version) ** ** 3. Transfer learning (+ Fine Tuning) ** ** 4. Build your own model ** ** 5. Model building and learning with TensorFLow2 (Expert Version) **

Other useful things to know

** [1]. When using your own dataset ** ** [2]. About Augmentaion ** [3]. TensorBoard [4]. TFRecord

1. TensorFlow basics

First, about the basics.

You can define a constant with tf.constant (value, dtype = None, shape = None, name ='Const', verify_shape = False).

>>> import tensorflow as tf
>>>
>>> tf.constant([1, 2, 3])
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 2, 3], dtype=int32)>
>>>
>>> b = tf.constant('Hello') #String ok
<tf.Tensor: shape=(), dtype=string, numpy=b'Hello'>
>>>

If you specify shape, all the elements have the same value.

>>> tf.constant(3, shape=[1, 3])
<tf.Tensor: shape=(1, 3), dtype=int32, numpy=array([[3, 3, 3]], dtype=int32)>
>>>
>>>

--Addition tf.add (), subtraction tf.subtract (), multiplication tf.mul (), division tf.divide ()

>>> tf.add(2,3)
<tf.Tensor: shape=(), dtype=int32, numpy=5>
>>>
>>> tf.subtract(5,3)
<tf.Tensor: shape=(), dtype=int32, numpy=2>
>>>
>>> tf.multiply(3,4)
<tf.Tensor: shape=(), dtype=int32, numpy=12>
>>>
>>> tf.divide(2,3)
0.6666666666666666

Convert Numpy to Tensor

Use tf.convert_to_tensor. Use .numpy () for a Numpy array.

>>> a = np.asarray([1,2,3])
>>> a
array([1, 2, 3])
>>> a.shape
(3,)
>>> tf.convert_to_tensor(a)
<tf.Tensor: shape=(3,), dtype=int64, numpy=array([1, 2, 3])>
>>> a
array([1, 2, 3])
>>> c = tf.convert_to_tensor(a)
>>> c 
<tf.Tensor: shape=(3,), dtype=int64, numpy=array([1, 2, 3])>
>>> c.numpy()
array([1, 2, 3])

Add dimension number tf.expand_dims (input, axis, name = None) Used when adding batch size to image size

>>> a = tf.constant([2,3])
>>> a.shape
TensorShape([2])
>>> b = tf.expand_dims(a,0)
>>> b.shape
TensorShape([1, 2])
>>>

tf.stack(values, axis=0, name='stack')

>>> x = tf.constant([1, 4]) 
>>> y = tf.constant([2, 5]) 
>>> z = tf.constant([3, 6]) 
>>> tf.stack([x, y, z], axis=0) 
<tf.Tensor: shape=(3, 2), dtype=int32, numpy=
array([[1, 4],
       [2, 5],
       [3, 6]], dtype=int32)>
>>> tf.stack([x, y, z], axis=1) 
<tf.Tensor: shape=(2, 3), dtype=int32, numpy=
array([[1, 2, 3],
       [4, 5, 6]], dtype=int32)>
>>> 

tf.concat(values, axis, name='concat')

>>> t1 = [[1, 2, 3], [4, 5, 6]] 
>>> t2 = [[7, 8, 9], [10, 11, 12]] 
>>> tf.concat([t1,t2],0)
<tf.Tensor: shape=(4, 3), dtype=int32, numpy=
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]], dtype=int32)>
>>> tf.concat([t1,t2],1)
<tf.Tensor: shape=(2, 6), dtype=int32, numpy=
array([[ 1,  2,  3,  7,  8,  9],
       [ 4,  5,  6, 10, 11, 12]], dtype=int32)>
>>> 

2. Easy model building and learning with keras (Beginner Version)

Next, I would like to do a classification problem with mnist data.

sample1.py



import tensorflow as tf

mnist = tf.keras.datasets.mnist 

(x_train, y_train), (x_test, y_test) = mnist.load_data() #Data reading
x_train, x_test = x_train / 255.0, x_test / 255.0 #Data normalization


#Model building
# Sequential API
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])


# optimizer, loss,metrics settings (learning settings)
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

#Learning
model.fit(x_train, y_train, epochs=5)

#Evaluation
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)

print('\nTest accuracy:', test_acc)

I think it's a writing style that you often see. This model modifies an image with input of 28x28 into a one-dimensional array 784 using Flatten (). After that, connect the fully connected layers, and the last fully connected layer 10 is the number of classes (the number you want to classify). Especially at the end, you can get the probability of each class by specifying softmax as activation. For learning and evaluation, you can use model.fit, model.evaluate, model.predict, etc.

The basic flow is (1) data reading, (2) data preprocessing, (3) model construction, (4) detailed learning settings, (5) learning, and (6) evaluation.

3. Transfer learning (+ Fine Tuning)

After building a simple model with mnist and learning it, let's try transfer learning next. Transfer learning is the use of weights learned in advance on a large number of images such as imagenet. It has the advantages of shortening the learning time and achieving some accuracy even with a small amount of data. Although transfer learning and Fine Tuning may not be so distinguished, transfer learning keeps the weight of the first layer fixed and learns only the layers that are replaced or added by yourself. Fine Tuning does not fix the weight of the first layer and retrains all parameters.

TensorFlow transfer learning uses tf.keras.applicacctions to load the model.

import tensorflow as tf
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D

#Input when loading the model_Please specify shape
# include_top =If set to False, the output layer will not be read.
IMG_SIZE = (224,224,3)
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SIZE,
                                               include_top = False,
                                               weights='imagenet')

#When fixing the weight of the base model
base_model.trainable = False


#Computational complexity can be reduced by using Global Average Pooling without fully connected layers
GAP_layer = GlobalAveragePooling2D()
#Since it is classified into 10 classes, it is 10. Replace this with your own task.
pred_layer = Dense(10, activation='softmax')

model = tf.keras.Sequential([
    base_model,
    GAP_layer,
    pred_layer
])

# model.summary()Please check the model at

There are other easy-to-use models, see Module: tf.keras.applications.

Although it is MobileNetV2, this model is a very "light model" that works even on edge terminals. A technique called Depthwise Separable Convolution that calculates the convolution separately in the spatial direction and the channel direction is used, or activation that maximizes the output value after passing ReLU through the activation function called ReLU6. It is a very interesting model that uses functions. If you are interested, please check it out.

4. Build your own model

Starting with TF2, you can use the sub classing API when building your model. Now that you can build a model like PyTorch, I will introduce it.



import tensorflow as tf

from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model

class Net(Model):
  def __init__(self):
    super(Net, self).__init__()
    self.conv1 = Conv2D(32, 3, activation='relu') #Conv2D(filters, kernel_size, activation)
    self.flatten = Flatten()
    self.d1 = Dense(128, activation='relu') # Dense(units, activation)
    self.d2 = Dense(10, activation='softmax') # Dense(units, activation)

  def call(self, x):
    x = self.conv1(x)
    x = self.flatten(x)
    x = self.d1(x)
    return self.d2(x)

#Create an instance of the model
model = Net()

--Defining layers to use in __init__ --Conv2D () is Conv2D (number of filters, kernel size, activation function) --Flatten () will convert the feature map to one dimension. Example 28x28-> 784 --Dense () is a fully connected layer. Specifies the number of dimensions in the output space --Write layers in the order of data flow with def call (self, x): --In PyTorch, when you pass data to Conv, you need to pass the number of filters for input and output, but TF2 doesn't have that. --Of course, you can initialize the kernel and bias, so please refer to Keras Documentation.

5. Model building and learning with TF2 (Expert Version)

For model construction, refer to 4. Build your own model.

Loss, optimizer, metrics settings


#Definition of loss function
loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
#optimizer settings
optimizer = tf.keras.optimizers.Adam()

###Used to calculate loss and accident
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')

test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')

Implementation of learning part (from TensorFlow tutorial)

def train_step(images, labels):
    with tf.GradientTape() as tape:  #Keep a history of calculations to be performed
        predictions = model(images) #Put images in the model to get predictions
        loss = loss_object(labels, predictions) #Calculate loss from correct label and prediction
  gradients = tape.gradient(loss, model.trainable_variables) #Differentiate the loss function with learnable parameters
  optimizer.apply_gradients(zip(gradients, model.trainable_variables)) #Updated with gradient information

  train_loss(loss)
  train_accuracy(labels, predictions)

About tf.GradientTape ()

――Differentiation is absolutely necessary for machine learning --Use tf.GradientTape where you want to keep the calculation history --In other words, tf.GradientTape is a class for finding the gradient.

import tensorflow as tf

x = tf.constant(3.0)
with tf.GradientTape() as tape:
    tape.watch(x)
    y = 3x+2
gradient = tape.gradient(y,x)
print(f'y = {y}')
print(f'x = {x}')
print(f'grad = {gradient}')

Output

y = 11.0
x = 3.0
grad = 3.0

Finally, I have posted the code for my train and val. It is full of Tsukkomi places, but please use it as a reference.


def train(model, train_dataset, loss_object, optimizer, train_loss, train_acc, CONFIG, train_count):
    cnt = 0
    max_value = train_count + CONFIG.batch_size
    with progressbar.ProgressBar(max_value=max_value) as bar:
        for imgs, labels in train_dataset:
            
            with tf.GradientTape() as tape:
                preds = model(imgs, training=True)
                loss = loss_object(labels, preds)
            gradients = tape.gradient(loss, model.trainable_variables)
            optimizer.apply_gradients(zip(gradients, model.trainable_variables))

            train_loss.update_state(values=loss)
            train_acc.update_state(labels, preds)
            cnt = cnt + CONFIG.batch_size
            bar.update(cnt)

    loss_t = train_loss.result().numpy()
    acc_t = train_acc.result().numpy()

    train_loss.reset_states()
    train_acc.reset_states()

    return loss_t, acc_t




def val(model, val_dataset, loss_object,optimizer, val_loss, val_acc,CONFIG, val_count):

    cnt = 0
    max_value = val_count + CONFIG.batch_size
    with progressbar.ProgressBar(max_value=max_value) as bar:
        for imgs, labels in val_dataset:
      
            preds = model(imgs, training=False)
            loss = loss_object(labels, preds)

            val_loss.update_state(values=loss)
            val_acc.update_state(labels, preds)
            cnt = cnt + CONFIG.batch_size
            bar.update(cnt)

    loss_v = val_loss.result().numpy()
    acc_v = val_acc.result().numpy()

    val_loss.reset_states()
    val_acc.reset_states()

    return loss_v, acc_v

-- tqdm doesn't work well in my environment and I'm using progressbar --acc and loss are updated with .update_state () --acc and loss metrics need to be reset every epoch, so reset with .reset_states () --You can specify training likemodel (imgs, training = False), which applies Dropout when training, but no longer applies Dropout when testing. Is

Other useful things to know

[1]. When using your own dataset

When learning with your own data set, I think there are roughly two types.

-(1) Specify a folder and load the image -(2) Read from the image path

(1) Specify a folder and load the image

--Use flow_from_directory () --You need to set target_size, batch_size, class_mode, etc. --Use in combination with Augmentation

train_aug = ImageDataGenerator(
        rescale=(1./255),
        horizontal_flip=True,
        vertical_flip=True,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        rotation_range=30,
        )

test_aug = ImageDataGenerator(
        rescale=(1./255),
        )

train_generator = train_aug.flow_from_directory(
        'data/train',
        target_size=(224,224),
        batch_size=batch_size,
        class_mode='categorical'
        )

test_generator = test_aug.flow_from_directory(
        'data/val',
        target_size=(224,224),
        batch_size=batch_size,
        class_mode='categorical'
        )

(2) Read from the image path

If you want to export the image path and label to csv and read it, I think this method is often used. I think any library will do when loading images. In the following, I will write until I get the file path of the image and create a dataset from it.



import os
import pathlib
import tensorflow as tf


#Data path specification
data_root_dir = 'data/train' 

data_root = pathlib.Path(data_root_dir) 
#Get image path
all_image_paths = [str(path) for path in list(data_root.glob('*/*'))] 
#Sort
all_image_paths = sorted(all_image_paths) 

#Verification
print(all_image_paths) 
print(len(all_image_paths)) 



#Get label:Get from directory name
label_names = sorted(item.name for item in data_root.glob('*/')) 
print(f' label : {label_names}') 

#Label dictionary creation dict{label:index} 
 
label_to_index = dict((label, index) for index, label in enumerate(label_names))
print(label_to_index) 


#Get labels for all images
all_image_labels = [label_to_index[pathlib.Path(image_path).parent.name] for image_path in all_image_paths] 
print(all_image_labels)
  

def load_data(all_image_paths, all_image_labels):
    img_list = [] 
    for filename in all_image_paths:
         #Loading images
         img = tf.io.read_file(filename) 
         #Decode
         img = tf.io.decode_image(img,channels = 3) 
         #If you do not resize or resize, an error will occur when creating a dataset.
         img = tf.image.resize(img, [224,224])
         img_list.append(img) 
     images = tf.stack(img_list, axis=0)
     labels = tf.stack(all_image_labels, axis=0)
     return tf.cast(images, tf.float32), tf.cast(labels, tf.int32)

#Get images and labels
imgs, labels  = load_data(all_image_paths, all_image_labels) 


#Shuffle data to create batches
dataset = tf.data.Dataset.from_tensor_slices((img_list, label_list)).shuffle(len(all_image_labels)).batch(8) 
#Verification
for data1, data2 in dataset.take(10):
     print(data1, data2) 

-** pathlib ** I want you to use it because it is convenient. --When creating a dataset, you can create it with tf.data.Dataset.from_tensor_slices () --Use shuffle () if you want to shuffle the dataset --Use batch () if you want to group by batch --Be careful as the behavior will change if you reverse the order of shuffle and batch.

[2]. Augmentaion

--There is a tf.image that can be used for Augmentaion, so please check it on the official website. --The following code is a simple example. Please use it as a function. ――If you can feel the atmosphere of writing ...


 image = tf.io.decode_image(contents=image,
                            channels=CONFIG.channels,
                            dtype=tf.dtypes.float32)

#Normalization
 image = (image / 0.5) -1

# data_aug =If True
 if data_aug:
     image = tf.image.random_flip_left_right(image=image)
     image = tf.image.resize_with_crop_or_pad(image=image,
                                           target_height=int(CONFIG.img_height*1.2),
                                           target_width=int(CONFIG.img_width*1.2))
     image = tf.image.random_crop(value=image, size=[CONFIG.img_height,CONFIG.img_width, CONFIG.channels])

else:
     image = tf.image.resize(image_tensor, [CONFIG.img_height, CONFIG.img_width])


--For Augmentation, albumentaions is recommended. ――I have a little habit of writing, but it's very convenient. (Cutout etc. are included as standard)

[3]. TensorBoard

--By using TensorBoard, you can easily check the transition of train acuuracy and loss. --Use a simple example to see how to use it

import tensorflow as tf
   
#Specify the log discharge location

     
writer = tf.summary.create_file_writer('tmp/mylogs')
   
with writer.as_default():     
    for step in range(100):
        tf.summary.scalar("acc/train", 0.7, step=step)
        tf.summary.scalar("acc/val", 0.5, step=step)
        tf.summary.scalar("loss/train", 0.7, step=step)
        tf.summary.scalar("loss/val", 0.5, step=step)
        writer.flush()

--Write in the form tf.summary.scalar (tag, value, step) ――In this example, it is specified by a constant such as 0.5 or 0.7, but you can pass the actual loss or acc. ――In addition to the value, you can also create images, so please try various things.

When checking, please specify the dir of the spit out log as follows and access http: // localhost: 6006 /

$ tensorboard --logdir='./tmp/mylogs'
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.1.1 at http://localhost:6006/ (Press CTRL+C to quit)

--It is one way to write the log to csv and then display it with matplot etc., but you can not confirm it until all the learning is completed. TensorBoard is convenient because you can see it in real time every time the value is updated.

[4]. TFRecord

--TFRecord is a binary version of the data in the format recommended by TensorFlow. --A large amount of data can be serialized and saved in a continuously readable format. --A large amount of data is read sequentially and input to the learner. --TFRecord saves each line information in units called Example ――You can think of it as a map with type information. --The following is an example of saving images and labels with TFRecoed.



def _bytes_feature(value):
    if isinstance(value, type(tf.constant(0.))):
        value = value.numpy()
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

def _float_feature(value):
    return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))

def _int64_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))


def get_info(data_root_dir):

    data_root = pathlib.Path(data_root_dir)
    all_image_paths = [str(path) for path in list(data_root.glob('*/*'))] 
    # Get label
    label_names = sorted(item.name for item in data_root.glob('*/')) 
    # dict {label:index} 
    label_to_index = dict((label, index) for index, label in enumerate(label_names))
    print(label_to_index) 
    # Get all images label 
    all_image_labels = [label_to_index[pathlib.Path(image_path).parent.name] for image_path in all_image_paths]

    return all_image_paths, all_image_labels 


def dataset_to_tfrecord(dataset_dir, tfrecord_name): 

    #Get images and labels for each directory
    image_paths, image_labels = get_info(dataset_dir) 
    image_paths_and_labels_dict = {} 
    #Convert to dictionary type
    for i in range(len(image_paths)): 
        image_paths_and_labels_dict[image_paths[i]] = image_labels[i]

    with tf.io.TFRecordWriter(path=tfrecord_name) as writer: 
        for image_path, label in image_paths_and_labels_dict.items(): 
            image_string = open(image_path, 'rb').read() 
            feature = { 
              'label' : _int64_feature(label), 
              'image' : _bytes_feature(image_string) 
            } 
            tf_example = tf.train.Example(features=tf.train.Features(feature=feature))
            writer.write(tf_example.SerializeToString()) 


For more information, see TensorFLow TFRecord and tf.Example.

At the end

We have seen how to classify images with TensorFLow. The Session and placeholder that were in TF1 have disappeared, the ʻEager Mode` has been defaulted, and keras has become a high-level API of the TensorFLow standard, making it easier to use personally. Was there. It's hard to get used to, but once I got used to it, TensorFLow was easy to write. In the future, I would like to be able to master both Pytorch and TensorFlow. There are many useful libraries such as ** pathlib ** and ** albumentaions ** introduced in the middle of the article, so if you are not using it, please use it.

References

Recommended Posts

For those who want to start machine learning with TensorFlow2
The first step of machine learning ~ For those who want to implement with python ~
For those who want to write Python with vim
Join Azure Using Go ~ For those who want to start and know Azure with Go ~
Loose articles for those who want to start natural language processing
Preparing to start "Python machine learning programming" (for macOS)
Anxible points for those who want to introduce Ansible
5 Reasons Processing is Useful for Those Who Want to Get Started with Python
Reference reference for those who want to code in Rhinoceros / Grasshopper
Environment construction for those who want to study python easily with VS Code (for Mac)
The first step for those who are amateurs of statistics but want to implement machine learning models in Python
For those who want to display images side by side as soon as possible with Python's matplotlib
[For those who want to use TPU] I tried using the Tensorflow Object Detection API 2
PyPI registration steps for those who want to make a PyPI debut
Python techniques for those who want to get rid of beginners
A memo for those who want quick socket communication with netcat
Amplify images for machine learning with python
An introduction to OpenCV for machine learning
Searching for properties to start with TensorFlow-Part 1
[Shakyo] Encounter with Python for machine learning
An introduction to Python for machine learning
A modern environment building procedure for those who want to get started with Python right away
[Short sentence] easygui for those who want to use a simple GUI with Python very easily
For those of you who glance at the log while learning with machine learning ~ Muscle training with LightGBM ~
Image analysis performed with google Colab for those who start space research
I analyzed Airbnb data for those who want to stay in Amsterdam
Memorandum of means when you want to make machine learning with 50 images
[Python] Easy introduction to machine learning with python (SVM)
An introduction to machine learning for bot developers
[Python] Collect images with Icrawler for machine learning [1000 images]
I want to start over with Django's Migrate
[For beginners] Introduction to vectorization in machine learning
Software training for those who start researching space
Python learning notes for machine learning with Chainer Chapters 11 and 12 Introduction to Pandas Matplotlib
Machine learning (TensorFlow) + Lotto 6
Introduction to machine learning
I tried to move machine learning (ObjectDetection) with TouchDesigner
PostgreSQL-For those who want to INSERT at high speed
Try to predict forex (FX) with non-deep machine learning
Site summary to learn machine learning with English video
[TensorFlow] I want to process windows with Ragged Tensor
Everything for beginners to be able to do machine learning
For those who are new to programming but have decided to analyze data with Python
I tried to build an environment for machine learning with Python (Mac OS X)
[Machine learning] Start Spark with iPython Notebook and try MLlib
Rebuilding an environment for machine learning with Miniconda (Windows version)
[TensorFlow] I want to master the indexing for Ragged Tensor
Japanese preprocessing for machine learning
Uncle SE with hardened brain tried to study machine learning
Try deep learning with TensorFlow
[TensorFlow 2 / Keras] How to run learning with CTC Loss in Keras
Do not learn with machine learning library TensorFlow ~ Fibonacci sequence
An introduction to machine learning
Introduction to Machine Learning with scikit-learn-From data acquisition to parameter optimization
I want to start a jupyter environment with one command
[NetworkX] I want to search for nodes with specific attributes
Machine learning with Python! Preparation
Made icrawler easier to use for machine learning data collection
How to use machine learning for work? 03_Python coding procedure
Image inspection machine for those who do not do their best
Machine learning Minesweeper with PyTorch