Permalink
Browse files

with BLAS, but unclean heap

  • Loading branch information...
1 parent 7bbbb07 commit 98d1f54b0e729d994dc5b3f9b8b697f1cb703eb7 Claudio A Andreoni committed Oct 3, 2011
Showing with 69 additions and 27 deletions.
  1. +2 −1 asgd/Makefile
  2. +9 −2 asgd/main.c
  3. +51 −24 asgd/naive_asgd.c
  4. +7 −0 asgd/naive_asgd.h
View
@@ -1,9 +1,10 @@
CC = gcc
+DEBUG = -g
CFLAGS = -Wall -std=c99 -O3
LIB = -lm -lgfortran -lopenblas
INCDIR = -I/opt/OpenBLAS/include
LIBDIR = -L/opt/OpenBLAS/lib
naive_asgd: main.c naive_asgd.c
@npinto

npinto Oct 3, 2011

Owner

can't be naive anymore ;-) let's call this one e.g. blas_asgd.c

@argoncloud

argoncloud via email Oct 3, 2011

Collaborator
@npinto

npinto Oct 3, 2011

Owner

Sounds good, but you keep in mind that you may have to become comfortable w/ the python stack sooner ;-)

- $(CC) $(CFLAGS) $(INCDIR) $(LIBDIR) $(LIB) -o naive_asgd main.c naive_asgd.c
+ $(CC) $(CFLAGS) $(DEBUG) $(INCDIR) $(LIBDIR) $(LIB) -o naive_asgd main.c naive_asgd.c
View
@@ -23,8 +23,8 @@ int main(
{
float last0 = powf(-1.0f, rand());
float last1 = powf(-1.0f, rand());
- matrix_set(y, i, 1, last0);
- matrix_set(ytst, i, 1, last1);
+ matrix_set(y, i, 0, last0);
+ matrix_set(ytst, i, 0, last1);
for (size_t j = 0; j < n_feats; ++j)
{
float val0 = 1.0f * rand() / RAND_MAX;
@@ -37,8 +37,15 @@ int main(
}
nb_asgd_t *clf = nb_asgd_init(n_feats, 1e-3f, 1e-6f, 4, false);
+ fit(clf, X, y);
+ matrix_t *ytrn_preds = matrix_init(row_major, n_feats, 1, sizeof(*ytrn_preds->data));
+ predict(clf, X, ytrn_preds);
+ matrix_t *ytst_preds = matrix_init(row_major, n_feats, 1, sizeof(*ytst_preds->data));
+ predict(clf, Xtst, ytst_preds);
nb_asgd_destr(clf);
+ matrix_destr(ytrn_preds);
+ matrix_destr(ytst_preds);
matrix_destr(X);
matrix_destr(y);
matrix_destr(Xtst);
View
@@ -9,6 +9,10 @@ matrix_t *matrix_init(
size_t ld)
{
matrix_t *m = malloc(sizeof(*m));
+ m->order = order;
+ m->rows = rows;
+ m->cols = cols;
+ m->ld = ld;
size_t major = order == row_major ? rows : cols;
m->data = calloc(major*ld, sizeof(*m->data));
return m;
@@ -145,7 +149,7 @@ static void durstenfeld_shuffle(matrix_t *m)
for (size_t i = m->rows-1; i > 0; --i) {
size_t j = rand() % (i+1);
// flip current row with a random row among remaining ones
- for (size_t k = 0; k < m->cols; ++i) {
+ for (size_t k = 0; k < m->cols; ++k) {
swap(m, i, k, j, k);
}
}
@@ -209,47 +213,52 @@ void partial_fit(
for (size_t i = 0; i < X->rows; ++i) {
// compute margin
- float margin = matrix_get(y, i, 1) * // TODO this will become a matrix
- cblas_sdsdot(X->cols, matrix_get(data->sgd_bias, 1, 1),
- matrix_row(X, i), sizeof(*X->data),
- matrix_row(data->sgd_weights, i), data->sgd_weights->ld);
+ float margin = matrix_get(y, i, 0) * // TODO this will become a matrix
+ cblas_sdsdot(X->cols, matrix_get(data->sgd_bias, 0, 0),
+ matrix_row(X, i), 1,
+ matrix_row(data->sgd_weights, i), 1);
@npinto

npinto Oct 3, 2011

Owner

This call looks good to me, what does valgrind or gdb says ?

@argoncloud

argoncloud via email Oct 3, 2011

Collaborator
// update sgd
if (data->l2_reg != 0)
{
// TODO this will become a matrix
cblas_sscal(data->sgd_weights->rows,
1 - data->l2_reg * data->sgd_step_size,
- data->sgd_weights->data, sizeof(*data->sgd_weights->data));
+ data->sgd_weights->data, 1);
}
if (margin < 1)
{
// TODO this will become a matrix
- cblas_saxpy(X->rows,
- data->sgd_step_size * matrix_get(y, i, 1),
- X->data, sizeof(*X->data),
- data->sgd_weights->data, sizeof(*data->sgd_weights->data));
-
+ matrix_t *sgd_weights = matrix_clone(data->sgd_weights);
+ cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
+ X->rows, data->sgd_weights->cols, X->cols,
+ data->sgd_step_size * matrix_get(y, i, 0),
+ X->data, X->ld,
+ sgd_weights->data, sgd_weights->ld,
+ 1.0f,
+ data->sgd_weights->data, data->sgd_weights->ld);
+ // matrix_destr(sgd_weights); FIXME
+
// TODO this will become a vector
- matrix_set(data->sgd_bias, 1, 1,
- data->sgd_step_size * matrix_get(y, i, 1));
+ matrix_set(data->sgd_bias, 0, 0,
+ data->sgd_step_size * matrix_get(y, i, 0));
}
// update asgd
matrix_t *asgd_weights = matrix_clone(data->asgd_weights);
cblas_sscal(asgd_weights->rows,
1 - data->asgd_step_size,
- asgd_weights->data, sizeof(*asgd_weights->data));
+ asgd_weights->data, 1);
cblas_saxpy(asgd_weights->rows,
data->asgd_step_size,
- data->asgd_weights->data, sizeof(*data->asgd_weights->data),
- asgd_weights->data, sizeof(*asgd_weights->data));
+ data->asgd_weights->data, 1,
+ asgd_weights->data, 1);
matrix_t *asgd_bias = matrix_clone(data->asgd_bias);
- matrix_set(asgd_bias, 1, 1,
- 1 - data->asgd_step_size * matrix_get(asgd_bias, 1, 1) +
- data->asgd_step_size * matrix_get(data->sgd_bias, 1, 1));
+ matrix_set(asgd_bias, 0, 0,
+ 1 - data->asgd_step_size * matrix_get(asgd_bias, 0, 0) +
+ data->asgd_step_size * matrix_get(data->sgd_bias, 0, 0));
// update step_sizes
data->n_observs += 1;
@@ -278,7 +287,7 @@ void fit(
for (uint64_t i = 0; i < data->n_iters; ++i) {
durstenfeld_shuffle(X);
durstenfeld_shuffle(y);
- //partial_fit(data, X, y);
+ partial_fit(data, X, y);
if (data->feedback) {
matrix_copy(data->sgd_weights, data->asgd_weights);
@@ -287,11 +296,29 @@ void fit(
}
}
-float predict(
+void predict(
nb_asgd_t *data,
- matrix_t *X)
+ matrix_t *X,
+ matrix_t *r)
{
- // TODO
- // find appropriate BLAS
+ // TODO r must be inited to zeros
+ cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
+ 1, r->rows, r->rows, 1.0f,
+ data->asgd_weights->data, data->asgd_weights->ld,
+ X->data, X->ld,
+ matrix_get(data->asgd_bias, 0, 0),
+ r->data, r->ld);
+
+ for (size_t i = 0; i < r->rows; ++i)
+ {
+ if (matrix_get(r, i, 0) >= 0)
+ {
+ matrix_set(r, i, 0, 1.0f);
+ }
+ else
+ {
+ matrix_set(r, i, 0, -1.0f);
+ }
+ }
}
View
@@ -71,5 +71,12 @@ nb_asgd_t *nb_asgd_init(
void nb_asgd_destr(
nb_asgd_t *data);
+void fit(nb_asgd_t *data, matrix_t *X, matrix_t *y);
+
+void partial_fit(nb_asgd_t *data, matrix_t *X, matrix_t *y);
+
+void predict(nb_asgd_t *data, matrix_t *X, matrix_t *r);
+
+
#endif

0 comments on commit 98d1f54

Please sign in to comment.