• 🏡 Home
  • 🚨 GDPR Compliant
  • ⚡️ Data Science
  • 📌 Machine Learning
  • 🔒 Privacy Preserving
  • 🏡 Home
  • 🚨 GDPR Compliant
  • ⚡️ Data Science
  • 📌 Machine Learning
  • 🔒 Privacy Preserving
Guide, machine-learning

Tensorflow Guida Italiano: primi passi con Tensorflow

Tensorflow Guida Italiano: primi passi con Tensorflow

Tensorflow guida italiano intende essere una guida in italiano per muovere i primi passi con Tensorflow, una libreria per il Machine Learning e il Deep Learning giunta alla versione di Tensorflow 2.0.

In Tensorflow 2: how to start? abbiamo seguito un esempio semplice, riproducendo una rete neurale artificiale per la conversione delle temperature.

Puoi trovare questo Tensorflow Tutorial in italiano qui.

Udacity ha invece sviluppato un corso tensorflow gratuito che puoi trovare qui.

Ok dovrebbe bastare.

Bentornato!

Possiamo finalmente iniziare a macinare informazioni utili, dopo aver accuratamente studiato un’introduzione SEO-friendly ricca di keywords per i crawler di Google, i bot usati nell’indicizzazione delle pagine web (Qui una spiegazione dettagliata).

Caro il mio marinaio, è giunto il momento di salpare alla volta di tensori, reti neurali, grafi e operazioni di derivazione.

Questa è la Tensorflow Guida in Italiano. Iniziamo!

Tensorflow Guida Italiano

First thing first: where can I code?

Tensorflow è piattaforma Open Source per Python, che consente lo sviluppo di sistemi di machine learning. Esiste anche una versione Web, chiamata Tensorflow.js, che per il momento non consideriamo.

Per iniziare a muovere i primi passi con Tensorflow hai bisogno di un ambiente Python configurato: in alternativa puoi avviare un documento Google Colab Online, che contiene tutto il necessario per programmare fin da subito.

In tal caso, ho realizzato per te questa breve guida che ti insegna a prendere dimestichezza con i Jupyter Notebook di Google Colab.

Prima cosa da fare: importare la versione più recente di Tensorflow.

Il 27 Marzo 2020 è stato compiuto lo switching della default version della libreria, passata dalla 1.x alla 2.x, rendendo superfluo andare a specificare quale versione importare.

Ci basta quindi scrivere:

# import Tensorflow
import tensorflow as tf

# for numerical computation and plotting
import numpy as np
from matplotlib import pyplot as plt

Ora, devi sapere una cosa.

Tensorflow è una parola composta da Tensor e flow

La prima indica un tensore, vale a dire una struttura dati generale definita da un singolo spazio vettoriale, di cui vettori, matrici, funzioni lineari ed endomorfismi costituiscono casi particolari.

La seconda indica il flusso che viene seguito per il calcolo di operazione complesse.

Tensorflow si configura quindi come un framework per la definizione e il calcolo di operazioni che coinvolgono tensori, rappresentazioni generiche di vettori e matrici a dimensioni maggiori.

Internamente, Tensorflow rappresenta i tensor come array n-dimensionali di datatypes base (int, string, etc..)

Esistono alcuni tensori particolari, tra cui:

tf.Variable(
 initial_value=None, trainable=None, validate_shape=True, caching_device=None,
    name=None, variable_def=None, dtype=None, import_scope=None, constraint=None,
    synchronization=tf.VariableSynchronization.AUTO,
    aggregation=tf.compat.v1.VariableAggregation.NONE, shape=None
)
tf.constant(
   value, dtype=None, shape=None, name='Const'
)

A eccezione del tf.Variable, i tensori sono immutabili.

Shape and Rank

Devi sapere che ogni elemento in un tensor condivide poi il data type, che è sempre noto, con quello degli altri elementi.

La shape di un tensor (vale a dire il numero di dimensioni e la lunghezza di ogni dimensione) può invece essere anche parzialmente nota.

Questo perché la maggior parte delle operazioni produce tensori di dimensioni completamente note (full-known) se quelle degli input sono altrettanto conosciute. In altri casi è possibile determinare la shape finale solo al termine dell’esecuzione dei grafi.

Un grafo è la rappresentazione, per mezzo di nodi, di operazioni eseguite sui tensori.

Il rank di un tensor è invece il numero di dimensioni (n-dimenions), e può essere considerato l’ordine di grandezza del tensore.

Per maggiori info, la documentazione è ricca di spunti.

Facciamo comunque qualche esempio:

# create 1-d Tensors from vectors and lists
sports = tf.constant(["Tennis", "Basketball"], tf.string)
numbers = tf.constant([3.141592, 1.414213, 2.71821], tf.float64)

print("`sports` is a {}-d Tensor with shape: {}".format(tf.rank(sports).numpy(), tf.shape(sports)))
print("`numbers` is a {}-d Tensor with shape: {}".format(tf.rank(numbers).numpy(), tf.shape(numbers)))

# Output:
#`sports` is a 1-d Tensor with shape: [2]
#`numbers` is a 1-d Tensor with shape: [3]

Perfetto.

Abbiamo preso dimestichezza con gli elementi base, i tensori, ora è arrivato il momento di passare all rappresentazione di tensor dalle dimensioni maggiori.

In applicazioni reali, come vedremo, avremo bisogno anche di 4-d Tensor, con i quali rappresentare ad esempio immagini in task di image preprocessing e computer vision.

Consideriamo dunque un tensor pronto a gestire 10 immagini quadrate a colori di 256px nello spazio RGB: 10 x 256*256*3.

'''Define a 4-d Tensor.'''
# Use tf.zeros to initialize a 4-d Tensor of zeros with size 10 x 256 x 256 x 3.
# You can think of this as 10 images where each image is RGB 256 x 256.

#  Creates a tensor with all elements set to zero.
images = tf.constant(tf.zeros((10,256,256,3), tf.int32, "The name of the operation"))

assert isinstance(images, tf.Tensor), "matrix must be a tf Tensor object"
assert tf.rank(images).numpy() == 4, "matrix must be of rank 4"
assert tf.shape(images).numpy().tolist() == [10, 256, 256, 3], "matrix is incorrect shape"

Computations | Tensorflow Guida Italiano alle operazioni

Per comprendere il flow dei dati e delle operazioni in Tensorflow, possiamo servirci dei grafi, rappresentazioni convenienti di computazioni.

Un grafo, o graph, e sarà quindi costituito da tensori, che gestiranno i dati, e dalle operazioni compiuti su di essi.

Vediamo una semplice operazione di somma: due tensori costanti e una sommatoria.

alt text
# Create the nodes in the graph, and initialize values
a = tf.constant(15)
b = tf.constant(61)

# Add them!
c1 = tf.add(a,b)
c2 = a + b # TensorFlow overrides the "+" operation so that it is able to act on Tensors
print(c1)
print(c2)

# Output:
# tf.Tensor(76, shape=(), dtype=int32)
# tf.Tensor(76, shape=(), dtype=int32)

Ora consideriamo un esempio più complesso:

Tensorflow Guida Italiano computational graph

Andiamo ora a costruire una funzione che riproduca le operazioni rappresentate nel grafo:

'''Defining Tensor computations''''

# Construct a simple computation function
def func(a,b):
  c = tf.add(a,b)
  d = tf.subtract(b,1)
  e = tf.multiply(c,d)
  return e

Quindi calcoliamo il risultato:

# Consider example values for a,b
a, b = 1.5, 2.5
# Execute the computation
e_out = func(a,b)
print(e_out)

# Output:
# tf.Tensor(6.0, shape=(), dtype=float32)

L’ouput è un semplice scalare, privo di dimensoni.

Tensorflow Guida Italiano alle Neural Network

Ovviamente, possiamo andare definire delle reti neurali artificiali ed eseguire operazioni complesse grazie a loro.

Devi sapere che Tensorflow usa una high-level API chiamata Keras, di cui abbiamo parlato in passato, che fornisce una potente e intuitiva interfaccia per creare e allenare reti neurali profonde, o Deep Neural Network

Nella nostra splendida introduzione al machine learning, che ti consiglio caldamente di leggere, così come in quella sulle reti neurali artificiali, che trovi invece qui, abbiamo descritto il perceptron.

Per semplicità, lo rappresenteremo graficamente come segue:

Tensorflow Guida Italiano single neuron perceptron

I tensor possono essere organizzati in Layer.

Secondo la documentazione ufficiale, un layery (a livello di tensorflow) è un classe che implementa operazioni comuni per le reti neurali quali convoluzione, gestione dei weight, dei loss e degli aggiornmenti generici.

Usiamo la struttura sottostante per definire un Layer e implementare il perceptron:

### Defining a network Layer ###

# n_output_nodes: number of output nodes
# input_shape: shape of the input
# x: input to the layer

class OurDenseLayer(tf.keras.layers.Layer):
  def __init__(self, n_output_nodes):
    super(OurDenseLayer, self).__init__()
    self.n_output_nodes = n_output_nodes

  def build(self, input_shape):
    d = int(input_shape[-1])
    # Define and initialize parameters: a weight matrix W and bias b
    # Note that parameter initialization is random!
    self.W = self.add_weight("weight", shape=[d, self.n_output_nodes]) # note the dimensionality
    self.b = self.add_weight("bias", shape=[1, self.n_output_nodes]) # note the dimensionality

  def call(self, x):
    '''TODO: define the operation for z (hint: use tf.matmul)'''
    z = tf.matmul(x,self.W) + self.b

    '''TODO: define the operation for out (hint: use tf.sigmoid)'''
    y = tf.sigmoid(z)
    return y

# Since layer parameters are initialized randomly, we will set a random seed for reproducibility
tf.random.set_seed(1)
layer = OurDenseLayer(3)
layer.build((1,2))
x_input = tf.constant([[1,2.]], shape=(1,2))
y = layer.call(x_input)

# test the output!
print(y.numpy())
mdl.lab1.test_custom_dense_layer_output(y)

# Output:
# [[0.26978594 0.45750412 0.66536945]]
# [PASS] test_custom_dense_layer_output
# True

Per convenienza, Tensorflow ha definito una serie di Layer comuni risparmiandocene in questo modo la codifica da zero.

Un esempio è il Dense Layer. (doc)

Per organizzare più layer, possiamo impiegare un modello di Keras chiamato Sequential (doc). Con questa API possiamo facilmente impilare più livelli e definire la nostra neural network.

''' Defining a neural network using the Sequential API '''

# Import relevant packages
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense

# Define the number of outputs
n_output_nodes = 3

# First define the model 
model = Sequential()

'''Define a dense (fully connected) layer to compute z'''
# Remember: dense layers are defined by the parameters W and b!
# You can read more about the initialization of W and b in the TF documentation :) 
# https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense?version=stable
dense_layer = Dense(n_output_nodes)

# Add the dense layer to the model
model.add(dense_layer)

Ora possiamo testare la nostra rete usando un piccolo input:

# Test model with example input
x_input = tf.constant([[1,2.]], shape=(1,2))

'''feed input into the model and predict the output!'''
model_output = model.predict(x_input)
print(model_output)

# Output:
# [[ 0.24415088  0.6485772  -1.9461871 ]]

In generale, useremo la Layer class per definire blocchi computazionali interni e la Model class per definre il modello esterno: l’oggetto da allenare.

In una variazione della ResNet, di cui abbiamo parlato qui, la ResNet50 ci sono diverse sottoclassi di modelli ResNet e una solo Model Class finale, quella che chiamiamo rete o modello.

Guida Tensorflow Italiano alle Subclass: ecco le sottoclassi

Per rendere la nostra Tensorflow Guida Italiano, degna di nota non possiamo non parlare delle sottoclassi.

Usando le sottoclassi possiamo creare diverse classi per il nostro modello, e poi definire il forwardpass attraverso la rete con la funzione call.

Le sottoclassi ci permettono di definire custom layer, custom training loops, custom activation function e custom model.

Ora ricreiamo la rete neurale precedente sostituendo le sottoclassi al Sequential Model

''' Defining a model using subclassing '''

from tensorflow.keras import Model
from tensorflow.keras.layers import Dense

class SubclassModel(tf.keras.Model):

  # In __init__, we define the Model's layers
  def __init__(self, n_output_nodes):
    super(SubclassModel, self).__init__()
    '''TODO: Our model consists of a single Dense layer. Define this layer.''' 
    self.dense_layer = Dense(n_output_nodes)

  # In the call function, we define the Model's forward pass.
  def call(self, inputs):
    return self.dense_layer(inputs)
  

Ora testiamolo!

n_output_nodes = 3
model = SubclassModel(n_output_nodes)

x_input = tf.constant([[1,2.]], shape=(1,2))

print(model.call(x_input))

# Output:
# Tf.Tensor([[ 0.62118787 -0.08692831  1.6387595 ]], shape=(1, 3), dtype=float32)

Le sottoclassi estendono le nostra capacità garantendoci una flessibilità pressoché infinita.

In questo potremmo ad esempio condizionare il ritorno della funzione call, modificando il comportamento della rete durante il training e l’inferenza.

Ad esempio, supponiamo di voler ritornare l’input senza alcuna perturbazione in alcune circostanze. Definiamo un argomento booleano nella funzione call che controlli questo comportamento:

''' Defining a model using subclassing and specifying custom behavior '''

from tensorflow.keras import Model
from tensorflow.keras.layers import Dense

class IdentityModel(tf.keras.Model):

  # As before, in __init__ we define the Model's layers
  # Since our desired behavior involves the forward pass, this part is unchanged
  def __init__(self, n_output_nodes):
    super(IdentityModel, self).__init__()
    self.dense_layer = tf.keras.layers.Dense(n_output_nodes, activation='sigmoid')

  '''TODO: Implement the behavior where the network outputs the input, unchanged, 
      under control of the isidentity argument.'''
  def call(self, inputs, isidentity=False):
    x = self.dense_layer(inputs)   
    '''TODO: Implement identity behavior'''
    return inputs if isidentity else x
 

Quindi eseguiamo il codice e gustiamoci il risultato:

n_output_nodes = 3
model = IdentityModel(n_output_nodes)

x_input = tf.constant([[1,2.]], shape=(1,2))
'''TODO: pass the input into the model and call with and without the input identity option.'''
out_activate = model.call(x_input)
out_identity = model.call(x_input,isidentity=True)

print("Network output with activation: {}; network identity output: {}".format(out_activate.numpy(), out_identity.numpy()))
 
# Output:
# Network output with activation: [[0.11969814 0.43011418 0.3474862 ]]; network identity output: [[1. 2.]]

Ora che sappiamo come definire nuovi Layer e costruire neural network in Tensorflow usando sia la Sequential API che la Subclass API è arrivato il momento d’implementare l’algoritmo di backpropagtion.

Guida Tensorflow per l’Automatic Differentiation

Un concetto chiave nel processo di training di una neural network, è quello di calcolo dell’errore compiuto nella previsione, e della sua retropropagazione ai layer precedenti.

Devi sapere che questi sono concetti fondamentali.

Sono veloce perché ne abbiamo ampiamente parlato nel post dedicato alla teoria delle reti neurali artificiali, che trovi qui.

Per il momento sappi che a livello matematico, l’allenamento di una rete neurale richiede che vengano eseguite operazioni computazionali, più o meno complesse, come il calcolo differenziale di una funzione.

La differenziazione automatica ci viene in aiuto.

Per Automatic Differentiation intendiamo allora un insieme di tecniche per calcolare la derivata di una funzione attraverso la Regola della Catena(chain rule).

Per mezzo di operazioni elementari (addizione, sottrazione etc…) e funzioni basilari (exp, log, etc…), consente di determinare una qualsiasi derivata, in modo preciso ed efficiente.

Questo insieme di tecniche è alla base dell’algoritmo di backpropagation.

Tensorflow Gradient Tape

Per ottimizzare la ricerca del minimo globale (global optima) della funzione di costo (objective function) esistono diversi algoritmi di ottimizzazione (trattai qui), di cui la discesa del gradiente (gradient descent) ne è il più comune. (come abbiamo visto qui).

Per il calcolo del gradiente in Tensorflow, abbiamo bisogno di un record delle operazioni compiute: tf.GradientTape (doc) corre in soccorso.

Quando il flusso è compiuto in avanti, espressione italiana aberrante per indicare il forward-pass o feed-forward system, tutte le operazioni sono ricordate su un tape.

Poi, il gradiente è calcolato svolgendo all’indietro il tape delle operazioni.

Ogni singolo tf.GradientTape può quindi calcolare un solo gradiente, in alternativa possiamo creare un persistent gradient tape e calcolare più gradienti.

Definiamo una semplice funzione quadratica e calcoliamone il gradiente (la derivata):

''' Gradient computation with GradientTape '''

# y = x^2
# Example: x = 3.0
x = tf.Variable(3.0)

# Initiate the gradient tape
with tf.GradientTape() as tape:
  # Define the function
  y = x * x
# Access the gradient -- derivative of y with respect to x
dy_dx = tape.gradient(y, x)

assert dy_dx.numpy() == 6.0

Nel prossimo blocco di codice useremo lo SGD (qui la spiegazione) per calcolare il minimo della objective function:


    \[L=(x-x_f)^2\]

xf è la variabile per il valore che vogliamo ottimizzare; L rappresenta la nostra funzione costo che intendiamo minimizzare.

Calcoliamo il risultato usandoGradientTape, benché sia possibile in questo caso risolverlo analiticamente, per preparare la strada a lavori futuri.

''' Function minimization with automatic differentiation and SGD '''

# Initialize a random value for our initial x
x = tf.Variable([tf.random.normal([1])])
print("Initializing x={}".format(x.numpy()))

learning_rate = 1e-2 # learning rate for SGD
history = []
epochs = 300
# Define the target value
x_f = 4

# We will run SGD for a number of iterations. At each iteration, we compute the loss, 
#   compute the derivative of the loss with respect to x, and perform the SGD update.
for i in range(epochs):
  with tf.GradientTape() as tape:
    '''TODO: define the loss as described above'''
    loss = (x - x_f)*(x - x_f)

  # loss minimization using gradient tape
  grad = tape.gradient(loss, x) # compute the derivative of the loss with respect to x
  new_x = x - learning_rate*grad # sgd update
  x.assign(new_x) # update the value of x
  history.append(x.numpy()[0])

# Plot the evolution of x as we optimize towards x_f!
plt.plot(history)
plt.plot([0, epochs],[x,x_f])
plt.legend(('Predicted', 'True'))
plt.xlabel('Iteration')
plt.ylabel('x value')

# Output:
# Initializing x=[[-0.92759573]]
# Text(0, 0.5, 'x value')
esempio-gradienttape-italia-tesnorflow-simple-example-italino-guida-machine-learning-tensroflow-deep-learnng-neurl-network-italiano-esempio

Per sfruttare appieno le potenzialità dell’algoritmo di retropropagazione dell’errore, tracciamo i flussi in avanti (forward pass) sul tape, usiamo l’informazione per determinare il gradiente e infine questi gradienti per l’ottimizzazione attraverso il SGD.

Primi passi con tensorflow: il tuo primo progetto

Ora puoi finalmente cimentarti in qualcosa di concreto.

In questa Guida Tensorflow hai visto gli elementi fondamentali di questo framework.

Seguimi allora in quello che sarà il tuo primo progetto!

Andremo a realizzare una piccola rete neurale, e poi una più complessa rete neurale convoluzionale, per classificare alcune immagini.

TensorFlow MNIST Tutorial con CNN, la guida in italiano step by step per creare una CNN!

Tensorflow Guida: domande frequenti sui primi passi!

Ho pensato di raccogliere per te alcune domande e relative risposte sull’argomento: penso le troverai utili!

Quanto tempo ci vuole per imparare TensorFlow?

Il tempo per imparare TensorFlow dipende dalla costanza e dal numero di progetti, anche personali, su cui lavori. Con un impegno di 10-20 ore settimanali, in circa 6 mesi dovresti riuscire a diventare autonomo, avendo esplorato e compreso la sua struttura e funzionalità.

È difficile imparare TensorFlow?

Sì. La curva di apprendimento di TensorFlow è ripida, sebbene l’ausilio di alcune sue API (e.g. Keras) lo rendano meno ostico. PyTorch, l’alternativa a TF, è più semplice e adattata alla creazione rapida di prototipi e progetti del weekend, mentre TensorFlow è pensato per ambienti di produzione e scalabili (i.e. professionali).

Quali sono i requisiti per iniziare con Tensorflow?

Per iniziare a studiare TensorfFlow devi avere dimestichezza con Python, conoscere le strutture dati di NumPy, e trovarti a tuo agio con un edior di codice, o IDE (e.g. Jupyter Notebook, Google Colab, VS Code, PyCharm etc.)

Per il momento è tutto!

Per aspera, ad astra.

Un caldo abbraccio, Andrea.

Written by Andrea Provino - Aprile 2, 2020
Tags | deep learning, guida, machine learning, neural network, tensorflow

You Might Also Like

Guida segmentazione semantica | Tensorflow, machine learning e computer vision

Dicembre 26, 2018

Real Time Face Detection WebSite using Javascript | Guida Italiano

Ottobre 9, 2019

Overplotting: cos’è e come porvi rimedio | Towards Data Science

Gennaio 7, 2019
Next Post
Previous Post

Una pubblicità che non vedi se usi AdBlock

EXPAND YOUR KNOWLEDGE

  • Blockchain Developer

    Circuito aritmetico

    Novembre 1, 2022
  • machine-learning

    Un nuovo inizio

    Settembre 4, 2021
  • Zero Knwoledge Proof Article Privacy Preserving

    Zero Knowledge Proof: zk-SNARK e zk-STARK | Prova a conoscenza zero

    Luglio 8, 2021
  • oblivious-transfer-spiegazione-italiano-ot-explanation Privacy Preserving

    Oblivious Transfer (OT)

    Luglio 6, 2021
  • Aleo Studio Website Preview machine-learning

    Aleo Studio: un IDE per Zero-Knowledge Proofs Applications

    Luglio 1, 2021
  • privacy-enhancing-technologies-data-machine-learning-data-science Privacy Preserving

    Perché il Privacy Tech è un vantaggio competitivo micidiale

    Giugno 17, 2021
  • bloom-filter-spiegazione-italian Privacy Preserving

    Bloom Filter

    Giugno 3, 2021
  • trusted-execution-environment-tee-data-science-come-fuziona Data Science, Privacy Preserving

    Trusted Execution Environment | Cos’è un TEE?

    Giugno 2, 2021
  • Crypto Custody services machine-learning

    Crypto Custody: Guida alla custodia delle criptomonete

    Maggio 26, 2021
  • deep-q-learning-q-learning-reinforcement-learning machine-learning

    Deep Q-Learning

    Aprile 27, 2021

Quello che Google pensa ti possa piacere

Prodotti che i Cookie dicono potresti trovare interessanti

AI Blog - © 2019-2021 Andrea Provino