Skip to content

Instantly share code, notes, and snippets.

@ahmetaa
Created April 15, 2013 14:56
Show Gist options
  • Save ahmetaa/5388710 to your computer and use it in GitHub Desktop.
Save ahmetaa/5388710 to your computer and use it in GitHub Desktop.
library gmm;
import 'dart:math';
class DiagonalGaussian {
List<double> means;
List<double> variances;
List<double> negativeHalfPrecisions;
double logPrecomputedDistance;
DiagonalGaussian(this.means, this.variances) {
// instead of using [-0.5 * 1/var[d]] during likelihood calculation we pre-compute the values.
// This saves 1 mul 1 div operation.
negativeHalfPrecisions = new List<double>(variances.length);
for (int i = 0; i < negativeHalfPrecisions.length; i++) {
negativeHalfPrecisions[i] = -0.5 / variances[i];
}
// calculate the precomputed distance.
// -0.5*SUM[d=1..D] ( log(2*PI) + log(var[d]) ) = -0.5*log(2*PI)*D -0.5 SUM[d=1..D](log(var[d]))
double val = -0.5 * log(2 * PI) * variances.length;
for (double variance in variances) {
val -= (0.5 * log(variance));
}
logPrecomputedDistance = val;
}
/// Calculates linear likelihood of a given vector.
double logLikelihood(List<double> data) {
double res = 0.0;
for (int i = 0; i < means.length; i++) {
final double dif = data[i] - means[i];
res += ((dif * dif) * negativeHalfPrecisions[i]);
}
return logPrecomputedDistance + res;
}
/// Calculates linear likelihood of a given vector.
double likelihood(List<double> data) {
double result = 1.0;
for (int i = 0; i < means.length; i++) {
double meanDif = data[i] - means[i];
result *= (1 / sqrt(2 * PI * variances[i])) *
exp(-0.5 * meanDif * meanDif / variances[i]);
}
return result;
}
int get dimension => means.length;
}
class Gmm {
List<double> mixtureWeights;
List<DiagonalGaussian> gaussians;
Gmm(this.mixtureWeights, this.gaussians);
double likelihood(List<double> data) {
double sum = 0.0;
for (int i = 0; i < gaussians.length; ++i) {
sum += mixtureWeights[i]*gaussians[i].likelihood(data);
}
return sum;
}
}
Random random = new Random(0xcafebabe);
double _random() {
return random.nextInt(10) / 10 + 0.1;
}
class GaussData {
List<double> means;
List<double> variances;
int dimension;
double weight;
GaussData(this.means, this.variances){
this.dimension = means.length;
}
GaussData.random(this.dimension) {
means = new List(dimension);
variances = new List(dimension);
for(int i = 0 ; i<dimension; i++){
means[i]=_random();
variances[i] = _random();
}
weight = _random();
}
}
Gmm getGmm(List<GaussData> gd) {
var gaussList = new List();
var weightList = new List();
for(int a = 0; a<gd.length; a++) {
gaussList.add(new DiagonalGaussian(gd[a].means, gd[a].variances));
weightList.add(gd[a].weight);
}
return new Gmm(weightList, gaussList);
}
class InputData {
List<List<double>> data;
int size;
int dimension;
InputData.random(this.size, this.dimension){
data = new List<List<double>>(size);
for (int i = 0; i < data.length; i++) {
data[i] = new List<double>(dimension);
for (int j = 0; j < dimension; j++) {
data[i][j] = _random();
}
}
}
}
void calculate(DiagonalGaussian gaussian, List data) {
Stopwatch sw = new Stopwatch()..start();
double tot = 0.0;
for (int i = 0; i<data.length; ++i) {
tot= tot+ gaussian.likelihood(data[i]);
}
print("log-likelihood=$tot");
}
int perfList(GaussData gauss, InputData input) {
var d = new DiagonalGaussian(gauss.means, gauss.variances);
Stopwatch sw = new Stopwatch()..start();
double tot = 0.0;
for (int i = 0; i<input.size; ++i) {
tot= tot+ d.likelihood(input.data[i]);
}
sw.stop();
print("log-likelihood=$tot");
print("List Elapsed: ${sw.elapsedMilliseconds}");
return sw.elapsedMilliseconds;
}
main() {
print("Generating test data");
int gmmCount = 1000;
int gaussPerGmm = 8;
int dimension = 40;
int inputAmount = 1000;
int iterationCount = 7;
List<Gmm> gmms = new List(gmmCount);
for(int i = 0; i<gmmCount;i++) {
List<GaussData> gaussDataList = new List(gaussPerGmm);
for(int j = 0; j<gaussPerGmm;j++) {
gaussDataList[j]= new GaussData.random(40);
}
gmms[i]=getGmm(gaussDataList);
}
InputData dataLarge = new InputData.random(inputAmount,40);
List<int> times = new List(iterationCount);
print("calculating..");
for(int it = 0; it<iterationCount; it++) {
Stopwatch sw = new Stopwatch()..start();
double total = 0.0;
for(int i = 0; i<inputAmount;i++) {
for(int j = 0; j<gmmCount;j++) {
total+= gmms[j].likelihood(dataLarge.data[i]);
}
}
sw.stop();
times[it] = sw.elapsedMilliseconds;
print("List Elapsed: ${sw.elapsedMilliseconds}");
}
times.sort();
double tot = 0.0;
for(int it = 0; it<iterationCount; it++) {
if(it!=0 && it!=iterationCount-1)
tot = tot + times[it];
}
print("mean = ${tot/(iterationCount-2).toDouble()}");
print("Done.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment