In [2]:
# Imports
import numpy
import pandas
In [15]:
def generate_data():
# Generate Random Data
cluster_size = 1000 # number of data points in a cluster
dimensions = 2
# Cluster A random numbers
cA_offset = (5,5)
cA = pandas.DataFrame(numpy.random.rand(cluster_size, dimensions) + cA_offset, columns=["x", "y"])
# Cluster B random numbers
cB_offset = (1,1)
cB = pandas.DataFrame(numpy.random.rand(cluster_size, dimensions) + cB_offset, columns=["x", "y"])
# Cluster C random numbers
cC_offset = (5,1)
cC = pandas.DataFrame(numpy.random.rand(cluster_size, dimensions) + cC_offset, columns=["x", "y"])
# Assign targets to the clusters
cA["target"] = 0
cB["target"] = 1
cC["target"] = 2
return cA, cB, cC
cA, cB, cC = generate_data()
# Show sample data
cA.head()
Out[15]:
In [16]:
# Plot a small subset of the data
%matplotlib inline
import matplotlib.pyplot as plt
# Use head() to only plot some points
plt.scatter(cA['x'].head(), cA['y'].head())
plt.scatter(cB['x'].head(), cB['y'].head())
plt.scatter(cC['x'].head(), cC['y'].head())
plt.xlim([0, 7]) # show x-scale from 0 to 7
plt.ylim([0, 7])
Out[16]:
In [17]:
# Concat all the input data (required for our neural network)
# ignore_index=True reindexes instead of keeping the existing indexes
# This makes sure we don't have repeating indexes
input_data = pandas.concat([cA, cB, cC], ignore_index=True)
# Shuffle data set: https://stackoverflow.com/questions/29576430/shuffle-dataframe-rows
# This makes sure we don't bias our neural network on the order things are inputted
input_data = input_data.sample(frac=1).reset_index(drop=True)
input_data.head() # Show sample from input_data
Out[17]:
We're going to build a very simple neural network that looks like this
2 inputs -> [no hidden nodes] -> 3 outputs
The first input will correspond to the x-coordinate of each point, the second input to the y-coordinate. The outputs will represent each of our target classes. In other words, the output will be a vector of dimension 3 containing probabilities that the given input corresponds to each of the target classes.
Example:
In [18]:
import keras
# Before we build our model, we first need to manipulate our dataset a bit so that we can easily use it with Keras.
# For input layer, keras expects our dataset to be in the format: [[x1, y1], [x2, y2], [x3, y3], ...]
training_input = input_data[["x", "y"]].values
# For the output layer, keras expects the target classes to be one-hot encoded (https://en.wikipedia.org/wiki/One-hot)
# This basically means converting our list of target classes to a list with a vector for each of integer classes,
# with a 1 on the position that corresponds to the integer representing the class
# e.g. [0, 1, 2, 0, ...] -> [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], ...]
# Keras has a utility function to_categorical(...) that does exactly this
# Note: assumption is made that classes are labeled 0->n (starting a 0, no gaps)
training_output = keras.utils.to_categorical(input_data["target"].values)
training_input, training_output
Out[18]:
In [19]:
from keras.models import Sequential, Model
from keras.layers import Input, Dense
# 1. BUILD MODEL
# Build model with 2 inputs and 3 outputs
# Use the softmax activation function to make sure our output vector has values between 0 and 1
# (= probabilities of belonging to the respective class)
# Without the softmax function, the outputs wouldn't be squeezed between 0 and 1.
a = Input(shape=(2,))
b = Dense(3, activation='softmax')(a)
model = Model(inputs=a, outputs=b)
# Alternative way to build model:
# model = Sequential()
# model.add(Dense(units=3, input_dim=2))
# 2. COMPILE MODEL
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
# Loss options:
# - categorical_crossentropy -> For a multi-class classification problem
# - binary_crossentropy -> For a binary classification problem
# - mse -> For a mean squared error regression problem
# Optimizer options:
# - sgd -> Stochastic Gradient Descent
keras.utils.print_summary(model)
In [20]:
# Training model
model.fit(training_input, training_output, epochs=20)
Out[20]:
In [14]:
test_dataset = numpy.random.rand(10, dimensions) + cC_offset
classes = model.predict(test_dataset)
classes
Out[14]:
In [22]:
# Generate a dataset to evaluate our model
evaluation_dataset = generate_data()
# Concat, shuffle (same as before, but with new dataset)
evaluation_dataset = pandas.concat([evaluation_dataset[0], evaluation_dataset[1] , evaluation_dataset[2]], ignore_index=True) # concat dataset
input_data = input_data.sample(frac=1).reset_index(drop=True) # Shuffle dataset
input_data.head()
Out[22]:
In [23]:
# Determine input, output for model
evaluation_input = evaluation_dataset[["x", "y"]].values
evaluation_output = keras.utils.to_categorical(evaluation_dataset["target"].values)
In [30]:
loss_and_metrics = model.evaluate(evaluation_input, evaluation_output, batch_size=128)
print model.metrics_names[0], "=", loss_and_metrics[0]
print model.metrics_names[1], "=", loss_and_metrics[1]