<jupyter_start><jupyter_text>We need to tell Google Colab that we want the TF 2.0 version so the code can work properly.<jupyter_code>import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import random
tf.executing_eagerly()<jupyter_output><empty_output><jupyter_text>We also need to import our required libraries so we can use them in the next parts.<jupyter_code>a1 = tf.random.uniform(shape=[], minval=-5, maxval=5)
b1 = tf.random.uniform(shape=[], minval=-5, maxval=5)
c1 = tf.random.uniform(shape=[], minval=-5, maxval=5)<jupyter_output><empty_output><jupyter_text>At this part we get some random values for a, b and c variables since our polynomial equation looks something like this: a*x^2 + b*x + c<jupyter_code>a2 = tf.random.uniform(shape=[], minval=-5, maxval=5)
b2 = tf.random.uniform(shape=[], minval=-5, maxval=5)
c2 = tf.random.uniform(shape=[], minval=-5, maxval=5)

xs = tf.constant(range(0, 20), dtype=tf.float32)
ys = tf.constant(tf.add(tf.add(tf.multiply(tf.pow(xs, 2), a2), tf.multiply(xs, b2)), c2), dtype=tf.float32)
print(f"Start values: \nModel: ({a1})*x^2 + ({b1})*x + ({c1})\nRandom Values: ({a2})*x^2 + ({b2})*x + ({c2})")
# xs = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0], dtype=tf.float32)
# ys = tf.constant([45000.0, 50000.0, 60000.0, 80000.0, 110000.0, 150000.0, 200000.0, 300000.0, 500000.0, 1000000.0], dtype=tf.float32)<jupyter_output><empty_output><jupyter_text>You can either use the upper one or the bottom one while trying this out. The top one generates another random polynomial equation which we then try to find using our model. The bottom one on the other hand, is kind of well known dataset for trying out the polynomial regression. You may come accross that dataset whenever you are looking for polynomial regression tutorials.<jupyter_code>plt.plot(xs, ys, 'bo')<jupyter_output><empty_output><jupyter_text>Plotting the X and Y values before training our model so we can get an idea of how our data looks like.<jupyter_code>def mean_squared_error(predictions, labels):
    return tf.reduce_mean(tf.square(predictions - labels))

def stochastic_gradient_descent_optimizer(indexes, labels , predictions):
    result = tf.reduce_mean(2 * indexes * (predictions - labels)).numpy()
    print(f"SGD --> Indexes: {indexes.numpy()} | Labels: {labels.numpy()} | Predictions: {predictions.numpy()} | Result: {result}")
    return result
    
def predict(indexes):
    prediction = tf.add(tf.add(tf.multiply(tf.pow(indexes, 2), a1), tf.multiply(indexes, b1)), c1)
    print(f"Incoming: {indexes.numpy()} | Prediction: {prediction.numpy()}")
    return prediction<jupyter_output><empty_output><jupyter_text>Here, we declare our 3 main functions we need for our "thing" to become a bit of "Machine Learning Model". First one is Mean Squared Error. This function will tell a number based on how off our predictions are from the actual values. Next one is Stochastic Gradient Descent. This function will be acting as our optimizer in our model so we will be changing our a1, b1 and c1 values based on this value. And the final and the most important one(yes, all of them are very important but they won't make any sense without this one :D), our connection to model! With the prediction function, we can comminucate with our model and ask for predictions from it.<jupyter_code>EPOCHS = 25
SAMPLES = xs.shape[0]
BATCH_SIZE = 1
LEARNING_RATE = 0.0001

dataset = tf.data.Dataset.from_tensor_slices((xs , ys))
dataset = dataset.repeat(EPOCHS).batch(BATCH_SIZE)
iterator = dataset.__iter__()<jupyter_output><empty_output><jupyter_text>At this step, we are preparing our dataset to become iterable so we can train our model with the batches of data we just make here.<jupyter_code>num_features = len(xs)
epochs_plot = list()
loss_plot = list()

for i in range(EPOCHS):
    epoch_loss = list()
    for Q in range(int(SAMPLES/BATCH_SIZE)):
        x_batch, y_batch = iterator.get_next()
        output = predict(x_batch)
        loss_val = epoch_loss.append(mean_squared_error(y_batch , output).numpy())
        deriv_val = stochastic_gradient_descent_optimizer(x_batch, y_batch , output)
        # print(f"deriv_val: {deriv_val}")
        a1 -= (LEARNING_RATE * deriv_val)
        b1 -= (LEARNING_RATE * deriv_val)
        c1 -= (LEARNING_RATE * deriv_val)
    loss_val = np.array(epoch_loss).mean()
    epochs_plot.append(i + 1)
    loss_plot.append(loss_val)
    print('Loss is {}'.format(loss_val))<jupyter_output><empty_output><jupyter_text>And yet another very important step, training! At this step, we train our model using the functions we have defined a few steps ago.<jupyter_code>plt.plot(epochs_plot, loss_plot) 
plt.show()<jupyter_output><empty_output><jupyter_text>Here, we can see how our loss value lowered as we trained our model at each epoch.<jupyter_code>polynomial_points = list()
for i in range(len(xs)):
    polynomial_points.append(predict(xs[i]).numpy())
plt.plot(xs, ys, 'bo', xs, polynomial_points, 'r')<jupyter_output><empty_output><jupyter_text>And the final step! First, we just predict our values on the same X values as our dataset so we can match each other in the plot. After making the predictions, we just plot them both together and voila! We have just created and trained our own model for polynomial regression! You can get more information about this project (such as the math behind MSE and SGD) at my blog post which you can go with [this](https://blog.tekno.icu/2020/01/22/polynomial-regression-in-python-using-tensorflow-2-0/) link. We can also check how close our model became to the randomly generated quadratic equation if you have chosen to generate a random quadratic equation at the first step.<jupyter_code>print(f"End values: \nModel: ({a1})*x^2 + ({b1})*x + ({c1})\nRandom Values: ({a2})*x^2 + ({b2})*x + ({c2})")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11632270168855535, 'fraction_numerical': 0.02933651714139519, 'mean_word_length': 5.0578512396694215, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '6249', 'license': 'MIT', 'n_tokens_mistral': 2048, 'n_tokens_neox': 1950, 'n_words': 639, 'path': 'colab.ipynb', 'repo_name': 'msteknoadam/tf_polynomial_regression', 'size': '5863'}