File size: 6,233 Bytes
eda3ba1 |
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 |
# Model to generate Sine(x) values.
# To do: add self.dropout = nn.Dropout(0.1) # Dropout layer
#Created on Thu Oct 28 12:18:37 2021
# @author: aman (translated to pytorch by Gemini)
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
# Set seed for experiment reproducibility
seed = 1
np.random.seed(seed)
torch.manual_seed(seed)
# Number of sample datapoints
SAMPLES = 400
# Generate a uniformly distributed set of random numbers in the range from
# 0 to 2π, which covers a complete sine wave oscillation
x_values = np.random.uniform(
low=0, high=2*math.pi, size=SAMPLES).astype(np.float32)
print(x_values)
# Shuffle the values to guarantee they're not in order
np.random.shuffle(x_values)
# Calculate the corresponding sine values
y_values = np.sin(x_values).astype(np.float32)
# Plot our data. The 'b.' argument tells the library to print blue dots.
plt.plot(x_values, y_values, 'b.')
plt.show()
# Add a small random number to each y value
y_values += 0.01 * np.random.randn(*y_values.shape)
# Plot our data
plt.plot(x_values, y_values, 'b.')
plt.show()
# We'll use 60% of our data for training and 20% for testing. The remaining 20%
# will be used for validation. Calculate the indices of each section.
TRAIN_SPLIT = int(0.6 * SAMPLES)
TEST_SPLIT = int(0.2 * SAMPLES + TRAIN_SPLIT)
# Use np.split to chop our data into three parts.
# The second argument to np.split is an array of indices where the data will be
# split. We provide two indices, so the data will be divided into three chunks.
x_train, x_test, x_validate = np.split(x_values, [TRAIN_SPLIT, TEST_SPLIT])
y_train, y_test, y_validate = np.split(y_values, [TRAIN_SPLIT, TEST_SPLIT])
# Double check that our splits add up correctly
assert (x_train.size + x_validate.size + x_test.size) == SAMPLES
# Plot the data in each partition in different colors:
plt.plot(x_train, y_train, 'b.', label="Train")
plt.plot(x_test, y_test, 'r.', label="Test")
plt.plot(x_validate, y_validate, 'y.', label="Validate")
plt.legend()
plt.show()
# Convert data to PyTorch tensors
x_train_tensor = torch.from_numpy(x_train).unsqueeze(1)
y_train_tensor = torch.from_numpy(y_train).unsqueeze(1)
x_test_tensor = torch.from_numpy(x_test).unsqueeze(1)
y_test_tensor = torch.from_numpy(y_test).unsqueeze(1)
x_validate_tensor = torch.from_numpy(x_validate).unsqueeze(1)
y_validate_tensor = torch.from_numpy(y_validate).unsqueeze(1)
# Define the PyTorch model
class SineModel(nn.Module):
def __init__(self):
super(SineModel, self).__init__()
self.fc1 = nn.Linear(1, 16)
self.fc2 = nn.Linear(16, 16)
self.fc3 = nn.Linear(16, 1)
self.relu = nn.ReLU()
def forward(self, x):
x = self.relu(self.fc1(x))
x = self.relu(self.fc2(x))
x = self.fc3(x)
return x
model = SineModel()
# Define optimizer and loss function
optimizer = optim.Adam(model.parameters(), lr=0.001) # lr = learning rate
loss_fn = nn.MSELoss()
# Train the model
epochs = 500
batch_size = 64
train_losses = []
val_losses = []
for epoch in range(1, epochs + 1):
# Training
model.train()
permutation = torch.randperm(x_train_tensor.size()[0])
epoch_train_loss = 0.0
for i in range(0, x_train_tensor.size()[0], batch_size):
indices = permutation[i:i+batch_size]
x_batch, y_batch = x_train_tensor[indices], y_train_tensor[indices]
optimizer.zero_grad()
y_pred = model(x_batch)
loss = loss_fn(y_pred, y_batch)
loss.backward()
optimizer.step()
epoch_train_loss += loss.item() * x_batch.size(0)
train_losses.append(epoch_train_loss/x_train_tensor.size(0))
# Validation
model.eval()
with torch.no_grad():
y_val_pred = model(x_validate_tensor)
val_loss = loss_fn(y_val_pred, y_validate_tensor).item()
val_losses.append(val_loss)
if epoch % 100 == 0:
print(f'Epoch {epoch}/{epochs}, Training Loss: {train_losses[-1]:.4f}, Validation Loss: {val_loss:.4f}')
# Draw a graph of the loss, which is the distance between
# the predicted and actual values during training and validation.
epochs_range = range(1, len(train_losses) + 1)
# Exclude the first few epochs so the graph is easier to read
SKIP = 0
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range[SKIP:], train_losses[SKIP:], 'g.', label='Training loss')
plt.plot(epochs_range[SKIP:], val_losses[SKIP:], 'b.', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.subplot(1, 2, 2)
# Draw a graph of mean absolute error, which is another way of
# measuring the amount of error in the prediction.
# We need to recalculate MAE because it was not stored during training
model.eval()
with torch.no_grad():
train_mae = torch.mean(torch.abs(model(x_train_tensor) - y_train_tensor)).item()
val_mae = torch.mean(torch.abs(model(x_validate_tensor) - y_validate_tensor)).item()
plt.plot([epochs_range[-1]], [train_mae], 'g.', label='Training MAE')
plt.plot([epochs_range[-1]], [val_mae], 'b.', label='Validation MAE')
plt.title('Training and validation mean absolute error')
plt.xlabel('Epochs (only final epoch shown for MAE)')
plt.ylabel('MAE')
plt.legend()
plt.tight_layout()
plt.show()
# Calculate and print the loss on our test dataset
model.eval()
with torch.no_grad():
y_test_pred_tensor = model(x_test_tensor)
test_loss = loss_fn(y_test_pred_tensor, y_test_tensor).item()
test_mae = torch.mean(torch.abs(y_test_pred_tensor - y_test_tensor)).item()
print(f'Test Loss: {test_loss:.4f}')
print(f'Test MAE: {test_mae:.4f}')
# Make predictions based on our test dataset
# y_test_pred has already been computed above when calculating test loss/MAE
# Graph the predictions against the actual values
plt.clf()
plt.title('Comparison of predictions and actual values')
plt.plot(x_test, y_test, 'b.', label='Actual values')
plt.plot(x_test, y_test_pred_tensor.detach().numpy(), 'r.', label='PyTorch predicted')
plt.legend()
plt.show()
# PyTorch does not have a direct equivalent to TensorFlow Lite built-in.
# For mobile/embedded |