Permalink
Browse files

C and Python interface, without feedback

  • Loading branch information...
1 parent 44e79f2 commit b4628b6e16324dea07a252281cc482321579a47b Claudio A Andreoni committed Feb 24, 2012
Showing with 63 additions and 179 deletions.
  1. +21 −4 asgd/Makefile
  2. +0 −132 asgd/asgd.py
  3. +8 −28 asgd/asgd_core.c
  4. +19 −10 asgd/casgd.py
  5. +11 −1 asgd/naive_asgd.py
  6. +4 −4 asgd/tests/asgd_unit.c
View
@@ -1,16 +1,33 @@
+# GCC
CC = gcc
-DEBUG = -g
-CFLAGS = -Wall -std=c99 -fPIC
+#DEBUG = -g
+CFLAGS = -Wall -std=c99 -fPIC -O3 -march=nocona
+# ICC
+#CC = icc
+#CFLAGS = -Wall -std=c99 -fPIC -O2 -xhost -ipo -fno-fnalias
+
+# stock ATLAS
INCDIR = -I/usr/include/
LIBDIR = -L/usr/lib64/atlas
+# custom ATLAS
+#INCDIR = -I/home/cloud/projects/asgd/ATLASobj/include
+#LIBDIR = -L/home/cloud/projects/asgd/ATLASobj/lib
+
+# MKL
+#INCDIR = -I/opt/intel/mkl/include
+#LIBDIR = -L/opt/intel/mkl/lib/intel64
+
+MATHLIB = -lm
+#MATHLIB =
+
ifeq ($(TYPE),blas)
-LIBS = -lm -lcblas
+LIBS = $(MATHLIB) -lcblas
DEFS = -DASGD_BLAS
OBJS =
else
-LIBS = -lm
+LIBS = $(MATHLIB)
DEFS =
OBJS = simple_blas.o
endif
View
@@ -1,132 +0,0 @@
-"""Averaging Stochastic Gradient Descent Classifier
-
-naive, non-optimized implementation
-"""
-import ctypes as ct
-import numpy as np
-from numpy import dot
-from itertools import izip
-
-
-class ASGD(object):
-
- def __init__(self, n_features, sgd_step_size0=1e-2, l2_regularization=1e-3,
- n_iterations=10, feedback=False, dtype=np.float32):
-
- self.n_features = n_features
- self.n_iterations = n_iterations
- self.feedback = feedback
-
- assert l2_regularization > 0
- self.l2_regularization = l2_regularization
- self.dtype = dtype
-
- self.sgd_weights = np.zeros((n_features), dtype=dtype)
- self.sgd_bias = np.zeros((1), dtype=dtype)
- self.sgd_step_size0 = sgd_step_size0
- self.sgd_step_size = sgd_step_size0
- self.sgd_step_size_scheduling_exponent = 2. / 3
- self.sgd_step_size_scheduling_multiplier = l2_regularization
-
- self.asgd_weights = np.zeros((n_features), dtype=dtype)
- self.asgd_bias = np.zeros((1), dtype=dtype)
- self.asgd_step_size0 = 1
- self.asgd_step_size = self.asgd_step_size0
-
- self.n_observations = 0
- self.core_lib = ct.CDLL("./asgd_core.so")
-
-
- def partial_fit(self, X, y):
-
- input_req = ['A', 'O', 'W', 'C']
- output_req = ['A', 'O', 'W', 'C']
- np.require(self.sgd_weights, dtype=np.float32, requirements=output_req)
- np.require(self.sgd_bias, dtype=np.float32, requirements=output_req)
- np.require(self.asgd_weights, dtype=np.float32, requirements=output_req)
- np.require(self.asgd_bias, dtype=np.float32, requirements=output_req)
- np.require(X, dtype=np.float32, requirements=input_req)
- np.require(y, dtype=np.float32, requirements=input_req)
-
- sgd_step_size0 = ct.c_float(self.sgd_step_size0)
- sgd_step_size = ct.c_float(self.sgd_step_size)
- sgd_step_size_scheduling_exponent = \
- ct.c_float(self.sgd_step_size_scheduling_exponent)
- sgd_step_size_scheduling_multiplier = \
- ct.c_float(self.sgd_step_size_scheduling_multiplier)
- sgd_weights = self.sgd_weights
- sgd_bias = self.sgd_bias
-
- asgd_weights = self.asgd_weights
- asgd_bias = self.asgd_bias
- asgd_step_size = ct.c_float(self.asgd_step_size)
-
- l2_regularization = ct.c_float(self.l2_regularization)
-
- n_observations = ct.c_long(self.n_observations)
-
- self.core_lib.core_partial_fit(
- ct.byref(n_observations),\
- ct.byref(sgd_step_size),\
- ct.byref(asgd_step_size),\
- l2_regularization,\
- sgd_step_size0,\
- sgd_step_size_scheduling_exponent,\
- sgd_step_size_scheduling_multiplier,\
- sgd_weights.ctypes.data_as(ct.POINTER(ct.c_float)),\
- ct.c_size_t(sgd_weights.shape[0]),\
- ct.c_size_t(1),\
- sgd_bias.ctypes.data_as(ct.POINTER(ct.c_float)),\
- ct.c_size_t(1),\
- ct.c_size_t(1),\
- asgd_weights.ctypes.data_as(ct.POINTER(ct.c_float)),\
- ct.c_size_t(asgd_weights.shape[0]),\
- ct.c_size_t(1),\
- asgd_bias.ctypes.data_as(ct.POINTER(ct.c_float)),\
- ct.c_size_t(1),\
- ct.c_size_t(1),\
- X.ctypes.data_as(ct.POINTER(ct.c_float)),\
- ct.c_size_t(X.shape[0]),\
- ct.c_size_t(X.shape[1]),\
- y.ctypes.data_as(ct.POINTER(ct.c_float)),\
- ct.c_size_t(y.shape[0]),\
- ct.c_size_t(y.shape[1]))
-
- # --
- self.sgd_weights = sgd_weights
- self.sgd_bias = sgd_bias
- self.sgd_step_size = sgd_step_size.value
-
- self.asgd_weights = asgd_weights
- self.asgd_bias = asgd_bias
- self.asgd_step_size = asgd_step_size.value
-
- self.n_observations = n_observations.value
-
- def fit(self, X, y):
-
- assert X.ndim == 2
- assert y.ndim == 1
-
- n_points, n_features = X.shape
- assert n_features == self.n_features
- assert n_points == y.size
-
- n_iterations = self.n_iterations
-
- for i in xrange(n_iterations):
-
- idx = np.random.permutation(n_points)
- Xb = X[idx]
- yb = y[idx]
- self.partial_fit(Xb, yb)
-
- if self.feedback:
- self.sgd_weights = self.asgd_weights
- self.sgd_bias = self.asgd_bias
-
- def decision_function(self, X):
- return dot(self.asgd_weights, X.T) + self.asgd_bias
-
- def predict(self, X):
- return np.sign(self.decision_function(X))
View
@@ -4,23 +4,6 @@
#include "asgd_blas.h"
-#include <stdio.h>
-
-static void prt(float *x, size_t x_rows, size_t x_cols)
-{
- FILE *f = fopen("out.txt", "a");
- for (long j=0; j<x_rows; ++j)
- {
- for (long k=0; k<x_cols; ++k)
- {
- fprintf(f, "%f ", x[j*x_cols+k]);
- }
- fprintf(f, "\n");
- }
- fprintf(f, "\n");
- fclose(f);
-}
-
void core_partial_fit(
long *n_observs,
float *sgd_step_size,
@@ -46,20 +29,17 @@ void core_partial_fit(
float *asgd_bias,
size_t asgd_bias_rows,
size_t asgd_bias_cols,
-
+
float *X,
size_t X_rows,
size_t X_cols,
-
+
float *y,
size_t y_rows,
size_t y_cols)
{
- //prt(X, X_rows, X_cols);
- //prt(y, y_rows, y_cols);
-
- for (size_t i = 0; i < X_rows; ++i) {
-
+ for (size_t i = 0; i < X_rows; ++i)
+ {
// compute margin //
// TODO sgd_weights will become a matrix
// notice that each row in X is also a column because of the stride
@@ -96,7 +76,7 @@ void core_partial_fit(
cblas_sscal(asgd_weights_rows,
1 - *asgd_step_size,
asgd_weights, 1);
-
+
cblas_saxpy(asgd_weights_rows,
*asgd_step_size,
sgd_weights, 1,
@@ -108,13 +88,13 @@ void core_partial_fit(
// update step_sizes //
*n_observs += 1;
-
+
float sgd_step_size_scheduling =
1 + sgd_step_size0 * *n_observs * sgd_step_size_scheduling_mul;
-
+
*sgd_step_size = sgd_step_size0 /
pow(sgd_step_size_scheduling, sgd_step_size_scheduling_exp);
-
+
*asgd_step_size = 1.0f / *n_observs;
}
}
View
@@ -39,6 +39,13 @@ def __init__(self, n_features, sgd_step_size0=1e-2, l2_regularization=1e-3,
def partial_fit(self, X, y):
+ # force ndarrays to point to different data
+ if self.sgd_weights is self.asgd_weights:
+ self.asgd_weights = self.asgd_weights.copy(order='C')
+ if self.sgd_bias is self.asgd_bias:
+ self.asgd_bias = self.asgd_bias.copy(order='C')
+
+ # require that all array are in contiguous C format
input_req = ['A', 'O', 'C']
output_req = ['A', 'O', 'W', 'C']
sgd_weights = np.require(
@@ -60,6 +67,7 @@ def partial_fit(self, X, y):
X = np.require(X, dtype=np.float32, requirements=input_req)
y = np.require(y, dtype=np.float32, requirements=input_req)
+ # convert all parameters to the right C type
sgd_step_size0 = ct.c_float(self.sgd_step_size0)
sgd_step_size = ct.c_float(self.sgd_step_size)
sgd_step_size_scheduling_exponent = \
@@ -71,6 +79,7 @@ def partial_fit(self, X, y):
l2_regularization = ct.c_float(self.l2_regularization)
n_observations = ct.c_long(self.n_observations)
+ # get array sizes in the right format
sgd_weights_rows = ct.c_size_t(sgd_weights.shape[0])
sgd_weights_cols = ct.c_size_t(1)
if sgd_weights.ndim == 2:
@@ -157,17 +166,17 @@ def fit(self, X, y):
Xb = X[idx]
yb = y[idx]
- print "before"
- print self.sgd_weights
- print self.sgd_bias
- print self.asgd_weights
- print self.asgd_bias
+ #print "before"
+ #print self.sgd_weights
+ #print self.sgd_bias
+ #print self.asgd_weights
+ #print self.asgd_bias
self.partial_fit(Xb, yb)
- print "after"
- print self.sgd_weights
- print self.sgd_bias
- print self.asgd_weights
- print self.asgd_bias
+ #print "after"
+ #print self.sgd_weights
+ #print self.sgd_bias
+ #print self.asgd_weights
+ #print self.asgd_bias
if self.feedback:
self.sgd_weights = self.asgd_weights
self.sgd_bias = self.asgd_bias
View
@@ -110,8 +110,18 @@ def fit(self, X, y):
idx = np.random.permutation(n_points)
Xb = X[idx]
yb = y[idx]
- self.partial_fit(Xb, yb)
+ #print "before"
+ #print self.sgd_weights
+ #print self.sgd_bias
+ #print self.asgd_weights
+ #print self.asgd_bias
+ self.partial_fit(Xb, yb)
+ #print "after"
+ #print self.sgd_weights
+ #print self.sgd_bias
+ #print self.asgd_weights
+ #print self.asgd_bias
if self.feedback:
self.sgd_weights = self.asgd_weights
self.sgd_bias = self.asgd_bias
View
@@ -206,9 +206,9 @@ bool test_decision_function(double tolerance)
decision_function(clf, Xm, rm);
bool res = true;
printf("testing decision_function\n");
- for (size_t i = 0; i < 1; ++i)
+ for (size_t i = 0; i < 5; ++i)
{
- for (size_t j = 0; j < 5; ++j)
+ for (size_t j = 0; j < 1; ++j)
{
printf("exp: %f got: %f\n",
out_r[i][j],
@@ -263,9 +263,9 @@ bool test_predict(double tolerance)
predict(clf, Xm, rm);
bool res = true;
printf("testing decision_function\n");
- for (size_t i = 0; i < 1; ++i)
+ for (size_t i = 0; i < 5; ++i)
{
- for (size_t j = 0; j < 5; ++j)
+ for (size_t j = 0; j < 1; ++j)
{
printf("exp: %f got: %f\n",
out_r[i][j],

0 comments on commit b4628b6

Please sign in to comment.