In [ ]:
# import the modules
import sys
import GPy
import csv
import numpy as np
import cPickle as pickle
import matplotlib as mpl
import matplotlib.cm as cm
import scipy.stats as stats
from GPy.plotting import Tango
import sklearn.metrics as metrics
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from GPy.plotting.matplot_dep.visualize import matplotlib_show
%matplotlib notebook
In [ ]:
font = {'size' : 18}
mpl.rc('font', **font)
In [ ]:
# load all the files and create Data
mocapPath = '../Data/Exp9/'
names = ['K1S1P1T1','K1S1P2T1','K1S1P6T1']
nTypes = 1
paths = [mocapPath]
dataKeys = ['Marker']
dataFormats = ['Marker']
# read all the file names and save to dicts
Data = {}
# loop over all names
for fileName in names:
data = {}
for ind in range(nTypes):
dataName = paths[ind] + fileName + dataFormats[ind]
reader = csv.reader(open(dataName,"rb"), delimiter=',')
d = np.array(list(reader))
data[dataKeys[ind]] = d.astype('float')
Data[fileName] = data
In [ ]:
# create train, val and test data
dim = 36
key = 'Marker'
samplingFreq = 2
trainSize = 0
trainData = np.empty((0,dim))
trainNames = ['K1S1P1T1']
for fileName in trainNames:
trainData = np.concatenate((trainData,Data[fileName][key][::samplingFreq,:]),axis=0)
trainSize = trainData.shape[0]
#trainData[:,0::3] = -trainData[:,0::3]
#trainData[:,2::3] = -trainData[:,2::3]
In [ ]:
# Training Cloud BGPLVM Model
# model name
expName = 'bgplvmModel'
# set the overall parameters for bgplvm
qDim = 10
nSamples = trainData.shape[0]
# set the number of inducing inputs
nInducing = 100
In [ ]:
from sklearn.decomposition import PCA
pca = PCA(n_components=qDim)
pca.fit(trainData)
scalesPCA = pca.explained_variance_ratio_
scalesPCA = scalesPCA/scalesPCA.max()
trainX = pca.transform(trainData)
trainOut = pca.inverse_transform(trainX)
In [ ]:
# setting up the kernel
kernel = GPy.kern.RBF(qDim, variance=1., lengthscale=1./scalesPCA, ARD = True)
# exepriment with different X initializations
bgplvmModel = GPy.models.BayesianGPLVM(trainData,input_dim=qDim,num_inducing=nInducing,kernel=kernel,X=trainX)
# Phase 1: Optimizaition by fixing variance parameters
SNR = 1000
var = bgplvmModel.Y.var()
bgplvmModel.rbf.variance.fix(var)
bgplvmModel.Gaussian_noise.variance.fix(var/SNR)
initVardistIters = 100
bgplvmModel.optimize(messages=True, max_iters=initVardistIters)
# Phase 2: Optimize the model without any constraints
# training without constraints
trainIters = 1000
bgplvmModel.unconstrain_fixed()
bgplvmModel.optimize(messages=True, max_iters=trainIters)
# Save the model to file
pickle.dump(bgplvmModel,open('../Models/Exp9/model.p','wb'))
In [ ]:
class cloth_show(matplotlib_show):
"""Base class for visualizing motion capture data."""
def __init__(self, vals, limits, axes=None, connect=None, color='b'):
if axes==None:
fig = plt.figure()
axes = fig.add_subplot(111, projection='3d', aspect='equal')
if len(vals.shape)==1:
vals = vals[None,:]
matplotlib_show.__init__(self, vals, axes)
self.color = color
self.limits = limits
self.connect = connect
self.process_values()
self.initialize_axes()
self.axes.set_xticklabels([])
self.axes.set_yticklabels([])
self.axes.set_zticklabels([])
self.axes.set_xlabel('X Axis')
self.axes.set_ylabel('Y Axis')
self.axes.set_zlabel('Z Axis')
self.draw_edges()
self.draw_vertices()
self.axes.figure.canvas.draw()
def draw_vertices(self):
self.points_handle = self.axes.scatter(self.vals[:, 0], self.vals[:, 1], self.vals[:, 2], color=self.color)
def draw_edges(self):
self.line_handle = []
if self.connect != None:
x = []
y = []
z = []
self.I, self.J = np.nonzero(self.connect)
for i, j in zip(self.I, self.J):
x.append(self.vals[i, 0])
x.append(self.vals[j, 0])
x.append(np.NaN)
y.append(self.vals[i, 1])
y.append(self.vals[j, 1])
y.append(np.NaN)
z.append(self.vals[i, 2])
z.append(self.vals[j, 2])
z.append(np.NaN)
self.line_handle = self.axes.plot(np.array(x), np.array(y), np.array(z), '-', color=self.color)
def modify(self, vals):
if len(vals.shape)==1:
vals = vals[None,:]
self.vals = vals.copy()
self.axes_modify()
self.process_values()
self.draw_edges()
self.draw_vertices()
self.axes.figure.canvas.draw()
def process_values(self):
self.vals = self.vals.T.reshape((self.vals.shape[1]/3, 3))
def initialize_axes(self, boundary=0.001):
"""Set up the axes with the right limits and scaling."""
bs = [(self.limits[i,0]-self.limits[i,1])*boundary for i in range(3)]
self.axes.set_xlim([self.limits[0,1]-bs[0], self.limits[0,0]+bs[0]])
self.axes.set_ylim([self.limits[1,1]-bs[1], self.limits[1,0]+bs[1]])
self.axes.set_zlim([self.limits[2,1]-bs[2], self.limits[2,0]+bs[2]])
def axes_modify(self):
self.points_handle.remove()
if self.connect != None:
self.line_handle[0].remove()
In [ ]:
connect = np.asarray([[0,1,0,0,0,1,0,0,0,0,0,0],
[1,0,1,0,0,0,0,0,0,0,0,0],
[0,1,0,1,0,0,0,0,0,0,0,0],
[0,0,1,0,1,0,0,0,0,0,0,0],
[0,0,0,1,0,1,0,0,0,0,0,0],
[1,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,2,2,0,0,0],
[0,0,0,0,0,0,2,0,2,0,0,0],
[0,0,0,0,0,0,2,2,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,2,2],
[0,0,0,0,0,0,0,0,0,2,0,2],
[0,0,0,0,0,0,0,0,0,2,2,0]])
In [ ]:
model = pickle.load(open('../Models/Exp9/model.p','rb'))
fig, (latent_axes, sense_axes) = plt.subplots(1, 2)
plt.sca(latent_axes)
model.plot_latent(ax=latent_axes,marker='o')
latent_axes.set_xticks([])
latent_axes.set_yticks([])
limits = np.asarray([[trainData[:,0::3].max(),trainData[:,0::3].min()],
[trainData[:,1::3].max(),trainData[:,1::3].min()],
[trainData[:,2::3].max(),trainData[:,2::3].min()]])
data_show = cloth_show(trainData[0,:], limits, connect=connect)
dim_select = lvm_dimselect(model.X.mean[0, :].copy(), model, data_show,
latent_axes=latent_axes, sense_axes=sense_axes)
sense_axes.set_ylabel('ARD Weight', fontsize=15)
sense_axes.set_xlabel('Latent Dimensions', fontsize=15)
fig.canvas.draw()
In [ ]:
class lvm(matplotlib_show):
def __init__(self, vals, model, data_visualize, latent_axes=None, sense_axes=None, latent_index=[0,1], disable_drag=False):
"""Visualize a latent variable model
:param model: the latent variable model to visualize.
:param data_visualize: the object used to visualize the data which has been modelled.
:type data_visualize: visualize.data_show type.
:param latent_axes: the axes where the latent visualization should be plotted.
"""
if vals is None:
if isinstance(model.X, VariationalPosterior):
vals = model.X.mean.values
else:
vals = model.X.values
if len(vals.shape)==1:
vals = vals[None,:]
matplotlib_show.__init__(self, vals, axes=latent_axes)
if isinstance(latent_axes,mpl.axes.Axes):
self.cid = latent_axes.figure.canvas.mpl_connect('button_press_event', self.on_click)
if not disable_drag:
self.cid = latent_axes.figure.canvas.mpl_connect('motion_notify_event', self.on_move)
self.cid = latent_axes.figure.canvas.mpl_connect('axes_leave_event', self.on_leave)
self.cid = latent_axes.figure.canvas.mpl_connect('axes_enter_event', self.on_enter)
else:
self.cid = latent_axes[0].figure.canvas.mpl_connect('button_press_event', self.on_click)
if not disable_drag:
self.cid = latent_axes[0].figure.canvas.mpl_connect('motion_notify_event', self.on_move)
self.cid = latent_axes[0].figure.canvas.mpl_connect('axes_leave_event', self.on_leave)
self.cid = latent_axes[0].figure.canvas.mpl_connect('axes_enter_event', self.on_enter)
self.data_visualize = data_visualize
self.model = model
self.latent_axes = latent_axes
self.sense_axes = sense_axes
self.called = False
self.move_on = False
self.latent_index = latent_index
self.latent_dim = model.input_dim
self.disable_drag = disable_drag
# The red cross which shows current latent point.
self.latent_values = vals
self.latent_handle = self.latent_axes.plot([0],[0],'rx',mew=2)[0]
self.modify(vals)
self.show_sensitivities()
def modify(self, vals):
"""When latent values are modified update the latent representation and ulso update the output visualization."""
self.vals = vals.view(np.ndarray).copy()
y = self.model.predict(self.vals)[0]
self.data_visualize.modify(y)
self.latent_handle.set_data(self.vals[0,self.latent_index[0]], self.vals[0,self.latent_index[1]])
self.axes.figure.canvas.draw()
def on_enter(self,event):
pass
def on_leave(self,event):
pass
def on_click(self, event):
if event.inaxes!=self.latent_axes: return
if self.disable_drag:
self.move_on = True
self.called = True
self.on_move(event)
else:
self.move_on = not self.move_on
self.called = True
def on_move(self, event):
if event.inaxes!=self.latent_axes: return
if self.called and self.move_on:
# Call modify code on move
self.latent_values[:, self.latent_index[0]]=event.xdata
self.latent_values[:, self.latent_index[1]]=event.ydata
self.modify(self.latent_values)
def show_sensitivities(self):
# A click in the bar chart axis for selection a dimension.
if self.sense_axes != None:
self.sense_axes.cla()
self.sense_axes.bar(np.arange(self.model.input_dim), self.model.input_sensitivity(), color='b')
if self.latent_index[1] == self.latent_index[0]:
self.sense_axes.bar(np.array(self.latent_index[0]), self.model.input_sensitivity()[self.latent_index[0]], color='y', label='X Axis')
self.sense_axes.bar(np.array(self.latent_index[1]), self.model.input_sensitivity()[self.latent_index[1]], color='y', label='Y Axis')
else:
self.sense_axes.bar(np.array(self.latent_index[0]), self.model.input_sensitivity()[self.latent_index[0]], color='g', label='X Axis')
self.sense_axes.bar(np.array(self.latent_index[1]), self.model.input_sensitivity()[self.latent_index[1]], color='r',label='Y Axis')
self.sense_axes.legend()
self.sense_axes.set_xticks([])
self.sense_axes.set_yticks([])
self.sense_axes.figure.canvas.draw()
In [ ]:
class lvm_dimselect(lvm):
"""
A visualizer for latent variable models which allows selection of the latent dimensions to use by clicking on a bar chart of their length scales.
For an example of the visualizer's use try:
GPy.examples.dimensionality_reduction.BGPVLM_oil()
"""
def __init__(self, vals, model, data_visualize, latent_axes=None, sense_axes=None, latent_index=[0, 1], labels=None):
if latent_axes==None and sense_axes==None:
self.fig,(latent_axes,self.sense_axes) = plt.subplots(1,2)
elif sense_axes==None:
fig=plt.figure()
self.sense_axes = fig.add_subplot(111)
else:
self.sense_axes = sense_axes
self.labels = labels
lvm.__init__(self,vals,model,data_visualize,latent_axes,sense_axes,latent_index)
self.show_sensitivities()
print(self.latent_values)
print("use left and right mouse buttons to select dimensions")
def on_click(self, event):
if event.inaxes==self.sense_axes:
new_index = max(0,min(int(np.round(event.xdata-0.5)),self.model.input_dim-1))
if event.button == 1:
# Make it red if and y-axis (red=port=left) if it is a left button click
self.latent_index[1] = new_index
else:
# Make it green and x-axis (green=starboard=right) if it is a right button click
self.latent_index[0] = new_index
self.show_sensitivities()
self.latent_axes.cla()
self.model.plot_latent(which_indices=self.latent_index,
ax=self.latent_axes, labels=self.labels)
self.latent_handle = self.latent_axes.plot([0],[0],'rx',mew=2)[0]
self.modify(self.latent_values)
elif event.inaxes==self.latent_axes:
self.move_on = not self.move_on
self.called = True
def on_leave(self,event):
print(type(self.latent_values))
latent_values = self.latent_values.copy()
y = self.model.predict(latent_values[None,:])[0]
self.data_visualize.modify(y)