Machine Learning z Python i TensorFlow - Praktyczny przewodnik
Machine Learning Python
ai-mlMachine Learning z Python i TensorFlow - Praktyczny przewodnik
Machine Learning (uczenie maszynowe) rewolucjonizuje sposób, w jaki budujemy oprogramowanie. Zamiast programowania jawnych reguł, uczymy modele rozpoznawania wzorców w danych. TensorFlow, stworzony przez Google, jest jednym z najpotężniejszych frameworków do budowy i wdrażania modeli ML. W tym przewodniku przejdziemy od podstaw teoretycznych, przez architekturę TensorFlow, po praktyczne implementacje i deployment modeli produkcyjnych.
Podstawy Machine Learning#
Zanim zagłębimy się w TensorFlow, warto zrozumieć trzy główne paradygmaty uczenia maszynowego.
Uczenie nadzorowane (Supervised Learning)#
W uczeniu nadzorowanym model trenowany jest na parach (dane wejściowe, oczekiwany wynik). Na podstawie tych przykładów uczy się funkcji mapującej wejście na wyjście.
Typowe zastosowania:
- Klasyfikacja - rozpoznawanie obrazów, analiza sentymentu, wykrywanie spamu
- Regresja - przewidywanie cen, prognoza pogody, estymacja czasu dostawy
# Prosty przykład: klasyfikacja binarna
import tensorflow as tf
from tensorflow import keras
# Dane treningowe: cechy i etykiety
X_train = [[0.1, 0.2], [0.4, 0.6], [0.8, 0.9], [0.3, 0.1]]
y_train = [0, 0, 1, 0] # 0 = klasa A, 1 = klasa B
model = keras.Sequential([
keras.layers.Dense(16, activation='relu', input_shape=(2,)),
keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=50, verbose=0)
Uczenie nienadzorowane (Unsupervised Learning)#
Model analizuje dane bez etykiet, szukając ukrytych wzorców i struktur.
Typowe zastosowania:
- Klasteryzacja - grupowanie klientów, segmentacja obrazów
- Redukcja wymiarów - wizualizacja danych wielowymiarowych (PCA, t-SNE)
- Wykrywanie anomalii - identyfikacja oszustw, monitoring systemów
# Autoenkoder do wykrywania anomalii
encoder = keras.Sequential([
keras.layers.Dense(64, activation='relu', input_shape=(100,)),
keras.layers.Dense(32, activation='relu'),
keras.layers.Dense(16, activation='relu') # Bottleneck
])
decoder = keras.Sequential([
keras.layers.Dense(32, activation='relu', input_shape=(16,)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(100, activation='sigmoid')
])
autoencoder_input = keras.layers.Input(shape=(100,))
encoded = encoder(autoencoder_input)
decoded = decoder(encoded)
autoencoder = keras.Model(autoencoder_input, decoded)
autoencoder.compile(optimizer='adam', loss='mse')
Uczenie ze wzmocnieniem (Reinforcement Learning)#
Agent uczy się podejmowania decyzji w środowisku, otrzymując nagrody za dobre działania i kary za złe. Jest to paradygmat za sukcesem AlphaGo, robotyki i autonomicznych pojazdów.
Kluczowe pojecia:
- Agent - podmiot podejmujący decyzje
- Środowisko - świat, w którym działa agent
- Polityka (Policy) - strategia decyzyjna agenta
- Nagroda (Reward) - sygnał zwrotny ze środowiska
Architektura TensorFlow i Keras#
TensorFlow to kompleksowy ekosystem do uczenia maszynowego. Keras, będący wysokopoziomowym API TensorFlow, znacząco upraszcza budowę modeli.
Tensory - podstawowa struktura danych#
Tensor to wielowymiarowa tablica liczbowa. Nazwa TensorFlow pochodzi od przepływu tensorów przez graf obliczeniowy.
import tensorflow as tf
# Skalar (tensor 0-wymiarowy)
scalar = tf.constant(42)
print(scalar.shape) # ()
# Wektor (tensor 1-wymiarowy)
vector = tf.constant([1.0, 2.0, 3.0])
print(vector.shape) # (3,)
# Macierz (tensor 2-wymiarowy)
matrix = tf.constant([[1, 2], [3, 4], [5, 6]])
print(matrix.shape) # (3, 2)
# Tensor 3-wymiarowy (np. batch obrazów RGB)
images = tf.random.normal([32, 224, 224, 3])
print(images.shape) # (32, 224, 224, 3)
# Operacje na tensorach
a = tf.constant([[1, 2], [3, 4]])
b = tf.constant([[5, 6], [7, 8]])
print(tf.add(a, b)) # Element-wise addition
print(tf.matmul(a, b)) # Mnożenie macierzy
print(tf.reduce_mean(a)) # Średnia
Warstwy (Layers)#
Warstwy to fundamentalne bloki konstrukcyjne modeli. Każda warstwa wykonuje transformację danych wejściowych.
# Najpopularniejsze warstwy w Keras
# Dense - warstwa w pełni połączona
dense = keras.layers.Dense(128, activation='relu')
# Conv2D - warstwa konwolucyjna 2D
conv = keras.layers.Conv2D(64, kernel_size=(3, 3), activation='relu', padding='same')
# LSTM - Long Short-Term Memory
lstm = keras.layers.LSTM(256, return_sequences=True)
# Dropout - regularyzacja (zapobiega overfitting)
dropout = keras.layers.Dropout(0.3)
# BatchNormalization - normalizacja wsadowa
bn = keras.layers.BatchNormalization()
# Embedding - mapowanie indeksów na wektory gęste
embedding = keras.layers.Embedding(input_dim=10000, output_dim=128)
Modele - Sequential vs Functional API#
Keras oferuje dwa główne sposoby budowy modeli.
# 1. Sequential API - prosty stos warstw
model_sequential = keras.Sequential([
keras.layers.Dense(256, activation='relu', input_shape=(784,)),
keras.layers.Dropout(0.3),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
# 2. Functional API - elastyczne grafy (wiele wejść/wyjść, skip connections)
inputs = keras.layers.Input(shape=(784,))
x = keras.layers.Dense(256, activation='relu')(inputs)
x = keras.layers.Dropout(0.3)(x)
# Skip connection (residual)
skip = keras.layers.Dense(128)(inputs)
x = keras.layers.Dense(128, activation='relu')(x)
x = keras.layers.Add()([x, skip])
x = keras.layers.Dropout(0.2)(x)
outputs = keras.layers.Dense(10, activation='softmax')(x)
model_functional = keras.Model(inputs=inputs, outputs=outputs)
Pętla treningowa (Training Loop)#
Proces trenowania modelu składa się z kilku etapów: kompilacja, trening, ewaluacja.
# Kompilacja modelu
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=0.001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# Callbacki - monitorowanie i sterowanie treningiem
callbacks = [
keras.callbacks.EarlyStopping(
monitor='val_loss',
patience=5,
restore_best_weights=True
),
keras.callbacks.ReduceLROnPlateau(
monitor='val_loss',
factor=0.5,
patience=3
),
keras.callbacks.ModelCheckpoint(
filepath='best_model.keras',
monitor='val_accuracy',
save_best_only=True
),
keras.callbacks.TensorBoard(log_dir='./logs')
]
# Trening
history = model.fit(
X_train, y_train,
epochs=100,
batch_size=32,
validation_split=0.2,
callbacks=callbacks
)
# Ewaluacja na danych testowych
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f"Test accuracy: {test_acc:.4f}")
Popularne architektury sieci neuronowych#
CNN - Convolutional Neural Networks#
Sieci konwolucyjne dominują w przetwarzaniu obrazów. Filtry konwolucyjne automatycznie uczą się wykrywania cech wizualnych.
def build_cnn_classifier(input_shape=(224, 224, 3), num_classes=10):
"""Budowa klasyfikatora obrazów CNN."""
model = keras.Sequential([
# Blok konwolucyjny 1
keras.layers.Conv2D(32, (3, 3), activation='relu',
padding='same', input_shape=input_shape),
keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.BatchNormalization(),
# Blok konwolucyjny 2
keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.BatchNormalization(),
# Blok konwolucyjny 3
keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.BatchNormalization(),
keras.layers.Dropout(0.3),
# Klasyfikator
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# Użycie
cnn_model = build_cnn_classifier(num_classes=10)
cnn_model.summary()
Kluczowe warstwy CNN:
- Conv2D - wykrywanie lokalnych cech (krawędzie, tekstury, kształty)
- MaxPooling2D - redukcja wymiarów przestrzennych, zwiększanie pola widzenia
- GlobalAveragePooling2D - agregacja map cech do wektora
- BatchNormalization - stabilizacja treningu, szybsza zbieżność
RNN - Recurrent Neural Networks#
Sieci rekurencyjne przetwarzają dane sekwencyjne - tekst, szeregi czasowe, dźwięk. LSTM i GRU rozwiązują problem zanikającego gradientu.
def build_text_classifier(vocab_size=20000, max_length=200, num_classes=5):
"""Klasyfikator tekstu z dwukierunkowym LSTM."""
model = keras.Sequential([
keras.layers.Embedding(vocab_size, 128, input_length=max_length),
keras.layers.Bidirectional(
keras.layers.LSTM(64, return_sequences=True)
),
keras.layers.Bidirectional(keras.layers.LSTM(32)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# Generowanie tekstu z RNN
def build_text_generator(vocab_size, seq_length):
"""Model generowania tekstu znak po znaku."""
model = keras.Sequential([
keras.layers.Embedding(vocab_size, 256, input_length=seq_length),
keras.layers.LSTM(512, return_sequences=True),
keras.layers.LSTM(512),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dense(vocab_size, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
return model
Transformer - rewolucja w NLP i nie tylko#
Architektura Transformer, oparta na mechanizmie self-attention, zrewolucjonizowała NLP i coraz szerzej wkracza w wizję komputerową.
class TransformerBlock(keras.layers.Layer):
"""Blok Transformer z Multi-Head Attention."""
def __init__(self, embed_dim, num_heads, ff_dim, dropout_rate=0.1):
super().__init__()
self.attention = keras.layers.MultiHeadAttention(
num_heads=num_heads,
key_dim=embed_dim // num_heads
)
self.ffn = keras.Sequential([
keras.layers.Dense(ff_dim, activation='gelu'),
keras.layers.Dense(embed_dim)
])
self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)
self.layernorm2 = keras.layers.LayerNormalization(epsilon=1e-6)
self.dropout1 = keras.layers.Dropout(dropout_rate)
self.dropout2 = keras.layers.Dropout(dropout_rate)
def call(self, inputs, training=False):
# Multi-Head Self-Attention + Residual
attn_output = self.attention(inputs, inputs)
attn_output = self.dropout1(attn_output, training=training)
out1 = self.layernorm1(inputs + attn_output)
# Feed-Forward Network + Residual
ffn_output = self.ffn(out1)
ffn_output = self.dropout2(ffn_output, training=training)
return self.layernorm2(out1 + ffn_output)
def build_transformer_classifier(
vocab_size=20000, max_length=200, embed_dim=128,
num_heads=4, ff_dim=256, num_blocks=2, num_classes=5
):
"""Klasyfikator tekstu oparty na Transformer."""
inputs = keras.layers.Input(shape=(max_length,))
x = keras.layers.Embedding(vocab_size, embed_dim)(inputs)
# Positional encoding (prosty - learned)
positions = keras.layers.Embedding(max_length, embed_dim)(
tf.range(max_length)
)
x = x + positions
for _ in range(num_blocks):
x = TransformerBlock(embed_dim, num_heads, ff_dim)(x)
x = keras.layers.GlobalAveragePooling1D()(x)
x = keras.layers.Dense(64, activation='relu')(x)
x = keras.layers.Dropout(0.3)(x)
outputs = keras.layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-4),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
Transfer Learning - potega pretrenowanych modeli#
Transfer learning pozwala wykorzystac wiedzę z modeli trenowanych na ogromnych zbiorach danych. Zamiast trenowania od zera, dostrajamy pretrenowany model do naszego zadania.
def build_transfer_learning_model(num_classes, fine_tune_at=100):
"""
Klasyfikator obrazów z transfer learning (EfficientNetV2).
Trenujemy tylko wierzchnie warstwy, zamrażając bazę.
"""
# Pretrenowany model jako ekstraktor cech
base_model = keras.applications.EfficientNetV2B0(
weights='imagenet',
include_top=False,
input_shape=(224, 224, 3)
)
# Zamrożenie warstw bazowych
base_model.trainable = False
# Budowa modelu
model = keras.Sequential([
base_model,
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dropout(0.3),
keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-3),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model, base_model
def fine_tune_model(model, base_model, fine_tune_at=100):
"""
Etap 2: Fine-tuning - odmrażamy górne warstwy bazowego modelu.
Używamy niższego learning rate, aby nie zniszczyć pretrenowanych wag.
"""
base_model.trainable = True
for layer in base_model.layers[:fine_tune_at]:
layer.trainable = False
model.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-5),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# Użycie
model, base_model = build_transfer_learning_model(num_classes=5)
# Etap 1: Trening klasyfikatora (zamrożona baza)
model.fit(train_ds, epochs=10, validation_data=val_ds)
# Etap 2: Fine-tuning (odmrożone górne warstwy)
model = fine_tune_model(model, base_model, fine_tune_at=100)
model.fit(train_ds, epochs=10, validation_data=val_ds)
Popularne pretrenowane modele w TensorFlow:
- EfficientNetV2 - najlepsza równowaga dokładności i wydajności dla obrazów
- ResNet50/101 - klasyczna architektura z residual connections
- MobileNetV3 - zoptymalizowany dla urządzeń mobilnych
- BERT/DistilBERT - pretrenowane modele językowe (przez TF Hub lub Hugging Face)
Praktyczny przyklad: klasyfikacja obrazów#
Zbudujmy kompletny pipeline klasyfikacji obrazów z augmentacją danych i transfer learningiem.
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
# 1. Ładowanie i przygotowanie danych
BATCH_SIZE = 32
IMG_SIZE = (224, 224)
train_ds = keras.utils.image_dataset_from_directory(
'dataset/train',
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int',
shuffle=True,
seed=42
)
val_ds = keras.utils.image_dataset_from_directory(
'dataset/validation',
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int'
)
class_names = train_ds.class_names
num_classes = len(class_names)
# 2. Augmentacja danych
data_augmentation = keras.Sequential([
keras.layers.RandomFlip('horizontal'),
keras.layers.RandomRotation(0.2),
keras.layers.RandomZoom(0.2),
keras.layers.RandomContrast(0.2),
keras.layers.RandomTranslation(0.1, 0.1)
])
# 3. Optymalizacja pipeline'u danych
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
# 4. Budowa modelu z transfer learning
base_model = keras.applications.EfficientNetV2B0(
weights='imagenet', include_top=False, input_shape=(*IMG_SIZE, 3)
)
base_model.trainable = False
inputs = keras.layers.Input(shape=(*IMG_SIZE, 3))
x = data_augmentation(inputs)
x = keras.applications.efficientnet_v2.preprocess_input(x)
x = base_model(x, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(256, activation='relu')(x)
x = keras.layers.Dropout(0.3)(x)
outputs = keras.layers.Dense(num_classes, activation='softmax')(x)
model = keras.Model(inputs, outputs)
# 5. Trening
model.compile(
optimizer=keras.optimizers.Adam(1e-3),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
train_ds, epochs=20, validation_data=val_ds,
callbacks=[
keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),
keras.callbacks.ReduceLROnPlateau(patience=3, factor=0.5)
]
)
# 6. Wizualizacja wyników
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(history.history['accuracy'], label='Train')
ax1.plot(history.history['val_accuracy'], label='Val')
ax1.set_title('Accuracy')
ax1.legend()
ax2.plot(history.history['loss'], label='Train')
ax2.plot(history.history['val_loss'], label='Val')
ax2.set_title('Loss')
ax2.legend()
plt.savefig('training_history.png', dpi=150)
plt.show()
Praktyczny przyklad: analiza sentymentu (NLP)#
import tensorflow as tf
from tensorflow import keras
import tensorflow_datasets as tfds
# 1. Ładowanie zbioru IMDB Reviews
(train_data, test_data), info = tfds.load(
'imdb_reviews',
split=['train', 'test'],
as_supervised=True,
with_info=True
)
# 2. Tokenizacja i przygotowanie danych
VOCAB_SIZE = 20000
MAX_LENGTH = 300
# TextVectorization - wbudowana warstwa tokenizacji
text_vectorizer = keras.layers.TextVectorization(
max_tokens=VOCAB_SIZE,
output_mode='int',
output_sequence_length=MAX_LENGTH
)
# Dostosowanie do danych treningowych
train_texts = train_data.map(lambda text, label: text)
text_vectorizer.adapt(train_texts)
# 3. Przygotowanie datasetów
def preprocess(text, label):
text = text_vectorizer(tf.expand_dims(text, -1))
text = tf.squeeze(text, axis=0)
return text, label
BATCH_SIZE = 64
AUTOTUNE = tf.data.AUTOTUNE
train_ds = (train_data
.map(preprocess, num_parallel_calls=AUTOTUNE)
.shuffle(10000)
.batch(BATCH_SIZE)
.prefetch(AUTOTUNE))
test_ds = (test_data
.map(preprocess, num_parallel_calls=AUTOTUNE)
.batch(BATCH_SIZE)
.prefetch(AUTOTUNE))
# 4. Model: 1D CNN + Bidirectional LSTM
model = keras.Sequential([
keras.layers.Embedding(VOCAB_SIZE, 128, input_length=MAX_LENGTH),
keras.layers.Conv1D(128, 5, activation='relu', padding='same'),
keras.layers.MaxPooling1D(2),
keras.layers.Bidirectional(keras.layers.LSTM(64)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(1, activation='sigmoid')
])
model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
# 5. Trening
history = model.fit(
train_ds, epochs=10, validation_data=test_ds,
callbacks=[keras.callbacks.EarlyStopping(patience=3)]
)
# 6. Predykcja
def predict_sentiment(texts):
"""Predykcja sentymentu dla listy tekstów."""
vectorized = text_vectorizer(tf.constant(texts))
predictions = model.predict(vectorized)
for text, pred in zip(texts, predictions):
sentiment = "Pozytywny" if pred[0] > 0.5 else "Negatywny"
print(f"{sentiment} ({pred[0]:.2%}): {text[:80]}...")
predict_sentiment([
"This movie was absolutely fantastic! Great acting and storyline.",
"Terrible film. Waste of time. The plot made no sense at all."
])
TensorFlow.js - Machine Learning w przegladarce#
TensorFlow.js pozwala uruchamiać modele ML bezpośrednio w przeglądarce lub w Node.js, umożliwiając inferencję po stronie klienta bez komunikacji z serwerem.
// Instalacja: npm install @tensorflow/tfjs
import * as tf from '@tensorflow/tfjs';
// Ładowanie pretrenowanego modelu do klasyfikacji obrazów
async function classifyImage(imageElement) {
// Ładowanie modelu MobileNet
const model = await tf.loadGraphModel(
'https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/classification/5/default/1',
{ fromTFHub: true }
);
// Przetworzenie obrazu na tensor
const tensor = tf.browser.fromPixels(imageElement)
.resizeBilinear([224, 224])
.expandDims(0)
.div(255.0);
// Inferencja
const predictions = model.predict(tensor);
const topK = tf.topk(predictions, 5);
const indices = await topK.indices.data();
const values = await topK.values.data();
// Zwolnienie pamięci
tensor.dispose();
predictions.dispose();
return indices.map((idx, i) => ({
classIndex: idx,
confidence: values[i]
}));
}
// Konwersja modelu Keras do TensorFlow.js
// W Pythonie:
// import tensorflowjs as tfjs
// tfjs.converters.save_keras_model(model, 'tfjs_model/')
Zalety TensorFlow.js:
- Prywatność - dane nie opuszczają urządzenia użytkownika
- Niskie opóźnienia - brak round-trip do serwera
- Offline - model działa bez internetu
- Skalowanie - inferencja na urządzeniach użytkowników zamiast kosztownych GPU
Deployment modeli produkcyjnych#
TensorFlow Serving#
TensorFlow Serving to wydajny system do serwowania modeli w produkcji.
# Zapisanie modelu w formacie SavedModel
model.save('saved_model/image_classifier/1')
# Struktura katalogów:
# saved_model/
# image_classifier/
# 1/ <- wersja modelu
# saved_model.pb
# variables/
# docker-compose.yml - TensorFlow Serving
version: "3.8"
services:
tf-serving:
image: tensorflow/serving:latest
ports:
- "8501:8501" # REST API
- "8500:8500" # gRPC
volumes:
- ./saved_model:/models
environment:
MODEL_NAME: image_classifier
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
# Wywołanie REST API
import requests
import numpy as np
import json
def predict_via_serving(image_array):
"""Wysłanie zapytania do TensorFlow Serving."""
url = "http://localhost:8501/v1/models/image_classifier:predict"
payload = {
"instances": image_array.tolist()
}
response = requests.post(url, json=payload)
predictions = response.json()['predictions']
return np.array(predictions)
# Batch prediction
images = np.random.rand(8, 224, 224, 3).astype(np.float32)
results = predict_via_serving(images)
print(f"Predictions shape: {results.shape}")
Eksport do ONNX#
ONNX (Open Neural Network Exchange) to otwarty format pozwalający uruchamiać modele w różnych runtime'ach.
# Konwersja TensorFlow -> ONNX
# pip install tf2onnx
import tf2onnx
import onnxruntime as ort
# Konwersja
spec = (tf.TensorSpec((None, 224, 224, 3), tf.float32, name="input"),)
model_proto, _ = tf2onnx.convert.from_keras(
model, input_signature=spec, output_path="model.onnx"
)
# Inferencja z ONNX Runtime (szybsza niż TF dla CPU)
session = ort.InferenceSession("model.onnx")
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name
result = session.run(
[output_name],
{input_name: np.random.rand(1, 224, 224, 3).astype(np.float32)}
)
print(f"ONNX prediction: {result[0]}")
TensorFlow Lite - modele na urządzeniach mobilnych#
# Konwersja do TFLite z kwantyzacją
converter = tf.lite.TFLiteConverter.from_saved_model('saved_model/image_classifier/1')
# Kwantyzacja post-treningowa (zmniejsza model 4x)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# Opcjonalnie: pełna kwantyzacja int8 (wymaga kalibracji)
def representative_dataset():
for i in range(100):
yield [np.random.rand(1, 224, 224, 3).astype(np.float32)]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_types = [tf.float16]
tflite_model = converter.convert()
with open('model.tflite', 'wb') as f:
f.write(tflite_model)
print(f"TFLite model size: {len(tflite_model) / 1024 / 1024:.2f} MB")
TensorFlow vs PyTorch - porownanie#
Wybór frameworka zależy od kontekstu projektu. Oto kluczowe różnice:
| Aspekt | TensorFlow | PyTorch | |--------|-----------|---------| | Tryb wykonania | Eager + Graph (tf.function) | Eager domyślnie, TorchScript dla grafu | | API wysokopoziomowe | Keras (wbudowane) | torch.nn (wbudowane), Lightning | | Deployment | TF Serving, TFLite, TF.js | TorchServe, ONNX, ExecuTorch | | Mobilne/Edge | TFLite (dojrzały) | ExecuTorch (nowszy) | | Przeglądarka | TensorFlow.js (dojrzały) | ONNX.js / Transformers.js | | Ekosystem | TFX, TF Hub, TF Data | Hugging Face, PyTorch Ecosystem | | Popularność w badaniach | Spadająca | Dominująca | | Popularność w produkcji | Nadal silna | Rosnąca | | Debugging | Trudniejszy (graf) | Łatwiejszy (Pythonic) | | Dokumentacja | Obszerna, ale rozproszona | Spójna, dobrze zorganizowana |
Kiedy wybrać TensorFlow:
- Deployment na wielu platformach (web, mobile, embedded)
- Istniejąca infrastruktura TFX w organizacji
- Potrzeba TensorFlow.js do inferencji w przeglądarce
- Projekty produkcyjne wymagające TF Serving
Kiedy wybrać PyTorch:
- Badania naukowe i prototypowanie
- Praca z modelami z Hugging Face
- Preferowanie Pythonic API i łatwego debugowania
- Projekty wymagające najnowszych architektur z papierów naukowych
Dobre praktyki w projektach ML#
1. Zarządzanie eksperymentami#
import mlflow
# Logowanie eksperymentów z MLflow
mlflow.set_experiment("image-classification")
with mlflow.start_run(run_name="efficientnet-v2-finetune"):
# Logowanie hiperparametrów
mlflow.log_params({
"learning_rate": 1e-3,
"batch_size": 32,
"epochs": 20,
"model": "EfficientNetV2B0",
"fine_tune_layers": 50
})
# Trening
history = model.fit(train_ds, epochs=20, validation_data=val_ds)
# Logowanie metryk
mlflow.log_metrics({
"final_accuracy": history.history['accuracy'][-1],
"final_val_accuracy": history.history['val_accuracy'][-1],
"final_loss": history.history['loss'][-1]
})
# Logowanie modelu
mlflow.keras.log_model(model, "model")
2. Wersjonowanie danych#
# DVC (Data Version Control) - śledzenie zmian w danych
# dvc init
# dvc add dataset/
# git add dataset.dvc .gitignore
# git commit -m "Add training dataset v1"
# dvc push
3. Reprodukowalność#
import random
import numpy as np
def set_seeds(seed=42):
"""Ustawienie seedów dla reprodukowalności."""
random.seed(seed)
np.random.seed(seed)
tf.random.set_seed(seed)
# Deterministic operations (wolniejsze, ale reprodukowalne)
tf.config.experimental.enable_op_determinism()
set_seeds(42)
Podsumowanie#
TensorFlow w połączeniu z Keras oferuje kompletny ekosystem do budowy, trenowania i wdrażania modeli Machine Learning. Od prostych sieci Dense, przez zaawansowane architektury CNN, RNN i Transformer, po deployment na serwerach, urządzeniach mobilnych i w przeglądarkach - TensorFlow dostarcza narzędzia na każdym etapie cyklu życia modelu ML.
Kluczowe wnioski:
- Zacznij od transfer learningu - pretrenowane modele dają świetne wyniki przy minimalnej ilości danych
- Optymalizuj pipeline danych -
tf.dataz prefetch i cache znacząco przyspiesza trening - Monitoruj eksperymenty - MLflow lub TensorBoard to konieczność w poważnych projektach
- Testuj deployment wcześnie - TF Serving, TFLite i TF.js mają różne ograniczenia
Potrzebujesz wdrożyć Machine Learning w swojej aplikacji? Zespół MDS Software Solutions Group specjalizuje się w budowie inteligentnych rozwiązań opartych na AI i ML. Od klasyfikacji obrazów, przez analizę tekstu, po systemy rekomendacji - pomożemy Ci przejść od prototypu do produkcji. Skontaktuj się z nami i porozmawiajmy o Twoim projekcie!
Zespół ekspertów programistycznych specjalizujących się w nowoczesnych technologiach webowych.