#include <stdio.h>
#include <arrayfire.h>
#include "wines_data.h"
using namespace af;
using namespace std;
void pca(array& data, array& pvec, array& eigv, array& pcomp, array& norm) {
int n = data.dims()[0];
array means = mean(data);
array stdvs = stdev(data);
array sdata = (data - tile(means, n, 1)) / tile(stdvs, n, 1);
array V, D, E;
eigen(V, D, cov(sdata));
E = diag(D);
array val, idx;
sort(val, idx, -1*E);
array comps = matmul(sdata, V);
pvec = V;
eigv = E(idx);
pcomp = comps(span, idx);
norm = sdata;
}
void pca(array& data, array& pvec, array& eigv, array& pcomp) {
array norm;
pca(data, pvec, eigv, pcomp, norm);
}
void pca_demo(bool console) {
array wines = array(14, 178, wines_h);
array data = wines.T();
array pvec, eigv, pcmp, norm;
pca(data, pvec, eigv, pcmp, norm);
print(eigv);
array trim = pvec(span, seq(4));
array proj = matmul(pcmp, trim);
if (!console) {
fig("color","gray");
fig("sub",2,1,1); fig("title","Input");
plot3(data(span,1), data(span,2), data(span,3));
fig("sub",2,1,2); fig("title","14D->3D PCA");
plot3(proj(span,1), proj(span,2), proj(span,3));
fig("draw");
}
}
int main(int argc, char** argv) {
bool console = false;
if (argc > 2 || (argc == 2 && argv[1][0] != '-')) {
printf("usage: pca_demo [-]\n");
return -1;
} else if (argc == 2 && argv[1][0] == '-') {
console = true;
}
try {
printf("** ArrayFire PCA Demo **\n\n");
pca_demo(console);
} catch (af::exception& e) {
fprintf(stderr, "%s\n", e.what());
}
if (!console) {
printf("hit [enter]...");
getchar();
}
return 0;
}