예제 #1
0
/**
 * Implementation of the learning rule described in Bell & Sejnowski,
 * Vision Research, in press for 1997, that contained the natural
 * gradient (W' * W).
 *
 * Bell & Sejnowski hold the patent for this learning rule.
 *
 * SEP goes once through the mixed signals X in batch blocks of size B,
 * adjusting weights W at the end of each block.
 *
 * sepout is called every F counts.
 *
 * I suggest a learning rate (L) of 0.006, and a block size (B) of
 * 300, at least for 2->2 separation.  When annealing to the right
 * solution for 10->10, however, L < 0.0001 and B = 10 were most successful.
 *
 * @param X  "sphered" input matrix
 * @param W  weight matrix
 * @param B  block size
 * @param L  learning rate
 * @param F  interval to print training stats
 */
void sep96(matrix_t *X, matrix_t *W, int B, double L, int F)
{
    matrix_t *BI = m_identity(X->rows);
    m_elem_mult(BI, B);

    int t;
    for ( t = 0; t < X->cols; t += B ) {
        int end = (t + B < X->cols)
            ? t + B
            : X->cols;

        matrix_t *W0 = m_copy(W);
        matrix_t *X_batch = m_copy_columns(X, t, end);
        matrix_t *U = m_product(W0, X_batch);

        // compute Y' = 1 - 2 * f(U), f(u) = 1 / (1 + e^(-u))
        matrix_t *Y_p = m_initialize(U->rows, U->cols);

        int i, j;
        for ( i = 0; i < Y_p->rows; i++ ) {
            for ( j = 0; j < Y_p->cols; j++ ) {
                elem(Y_p, i, j) = 1 - 2 * (1 / (1 + exp(-elem(U, i, j))));
            }
        }

        // compute dW = L * (BI + Y'U') * W0
        matrix_t *U_tr = m_transpose(U);
        matrix_t *dW_temp1 = m_product(Y_p, U_tr);
        m_add(dW_temp1, BI);

        matrix_t *dW = m_product(dW_temp1, W0);
        m_elem_mult(dW, L);

        // compute W = W0 + dW
        m_add(W, dW);

        // print training stats
        if ( t % F == 0 ) {
            precision_t norm = m_norm(dW);
            precision_t angle = m_angle(W0, W);

            printf("*** norm(dW) = %.4lf, angle(W0, W) = %.1lf deg\n", norm, 180 * angle / M_PI);
        }

        // cleanup
        m_free(W0);
        m_free(X_batch);
        m_free(U);
        m_free(Y_p);
        m_free(U_tr);
        m_free(dW_temp1);
        m_free(dW);
    }
}
예제 #2
0
int main(int argc, char *argv[]) {

	vect3<TYP> r, s, t;

	cout << "\n\nZadej 1. vektor (r): ";

	cin >> r;

	cout << "\nr = " << r << ", jeho delka = " << abs(r) << "\n"
	     << "Opacny vektor = " << -r << ", jeho delka = " << abs(-r)
	     << "\n-r/2 = " << static_cast<TYP>(-0.5)*r
	     << "\nDelka polovicniho opacneho = "
	     << abs(static_cast<TYP>(-0.5)*r)
	     << "\n\nZadej 2. vektor (s): ";

	cin >> s;

	cout << "\ns = " << s << "\nr + s = " << r+s << "\nr - s = "
	     << r-s << "\nr . s = " << r*s << "\nr x s = " << r%s
	     << "\ns . r = " << s*r << "\ns x r = " << s%r
	     << " (opacny k r x s)\n\nZadej 3. vektor (t): ";

	cin >> t;

	cout << "\nt = " << t << "\nSmiseny soucin = " << m_product(r,s,t)
	     << "\n\n";
	
	return 0;
}
예제 #3
0
/**
 * Test matrix square root.
 */
void test_m_sqrtm()
{
	precision_t data[][5] = {
		{  5, -4,  1,  0,  0 },
		{ -4,  6, -4,  1,  0 },
		{  1, -4,  6, -4,  1 },
		{  0,  1, -4,  6, -4 },
		{  0,  0,  1, -4,  6 }
	};

	matrix_t *A = m_initialize(5, 5);
	fill_matrix_data(A, data);

	matrix_t *X = m_sqrtm(A);
	matrix_t *X_sq = m_product(X, X);

	printf("A = \n");
	m_fprint(stdout, A);
	printf("X = sqrtm(A) = \n");
	m_fprint(stdout, X);
	printf("X * X = \n");
	m_fprint(stdout, X_sq);

	m_free(A);
	m_free(X);
	m_free(X_sq);
}
예제 #4
0
/**
 * Test matrix inverse.
 */
void test_m_inverse()
{
	precision_t data[][3] = {
		{  1,  0,  2 },
		{ -1,  5,  0 },
		{  0,  3, -9 }
	};

	matrix_t *X = m_initialize(3, 3);
	fill_matrix_data(X, data);

	matrix_t *Y = m_inverse(X);
	matrix_t *Z = m_product(Y, X);

	printf("X = \n");
	m_fprint(stdout, X);
	printf("Y = inv(X) = \n");
	m_fprint(stdout, Y);
	printf("Y * X = \n");
	m_fprint(stdout, Z);

	m_free(X);
	m_free(Y);
	m_free(Z);
}
예제 #5
0
/**
 * Compute the projection matrix of a training set with ICA
 * using Architecture II.
 *
 * @param W_pca_tr  PCA projection matrix
 * @param P_pca     PCA projected images
 * @return projection matrix W_ica'
 */
matrix_t * ICA2(matrix_t *W_pca_tr, matrix_t *P_pca)
{
    // compute weight matrix W_I
    matrix_t *W_I = run_ica(P_pca);

    // compute W_ica' = W_I * W_pca'
    matrix_t *W_ica_tr = m_product(W_I, W_pca_tr);

    // cleanup
    m_free(W_I);

    return W_ica_tr;
}
예제 #6
0
/**
 * Compute the ICA weight matrix W_I for an input matrix X.
 *
 * @param X  mean-subtracted input matrix
 * @return weight matrix W_I
 */
matrix_t * run_ica(matrix_t *X)
{
    // compute whitening matrix W_z
    matrix_t *W_z = sphere(X);
    matrix_t *X_sph = m_product(W_z, X);

    // shuffle the columns of X_sph
    m_shuffle_columns(X_sph);

    // train the weight matrix W
    matrix_t *W = m_identity(X->rows);

    sep96_params_t params[] = {
        { 50, 0.0005, 5000, 1000 },
        { 50, 0.0003, 5000, 200 },
        { 50, 0.0002, 5000, 200 },
        { 50, 0.0001, 5000, 200 }
    };
    int num_sweeps = sizeof(params) / sizeof(sep96_params_t);

    int i, j;
    for ( i = 0; i < num_sweeps; i++ ) {
        printf("sweep %d: B = %d, L = %lf\n", i + 1, params[i].B, params[i].L);

        for ( j = 0; j < params[i].N; j++ ) {
            sep96(X_sph, W, params[i].B, params[i].L, params[i].F);
        }
    }

    // compute W_I = W * W_z
    matrix_t *W_I = m_product(W, W_z);

    // cleanup
    m_free(W_z);
    m_free(X_sph);
    m_free(W);

    return W_I;
}
예제 #7
0
void update_ahrs(float dt, float dcm_out[3][3], float gyr_out[3])
{
	static uint8_t i;

	read_mpu(v_gyr, v_acc);
	for (i=0; i<3; i++) {
		gyr_out[i] = v_gyr[i];
	}

	/**
	 * Accelerometer
	 *     Frame of reference: body
	 *     Units: G (gravitational acceleration)
	 *     Purpose: Measure the acceleration vector v_acc with components
	 *              codirectional with the i, j, and k vectors. Note that the
	 *              gravitational vector is the negative of the K vector.
	 */
	#ifdef ACC_WEIGHT
	// Take weighted average.
	#ifdef ACC_SELF_WEIGHT
	for (i=0; i<3; i++) {
		v_acc[i] = ACC_SELF_WEIGHT * v_acc[i] + (1-ACC_SELF_WEIGHT) * v_acc_last[i];
		v_acc_last[i] = v_acc[i];

		// Kalman filtering?
		//v_acc_last[i] = acc.get(i);
		//kalmanUpdate(v_acc[i], accVar, v_acc_last[i], ACC_UPDATE_SIG);
		//kalmanPredict(v_acc[i], accVar, 0.0, ACC_PREDICT_SIG);
	}
	#endif // ACC_SELF_WEIGHT
	acc_scale = v_norm(v_acc);

	/**
	 * Reduce accelerometer weight if the magnitude of the measured
	 * acceleration is significantly greater than or less than 1 g.
	 *
	 * TODO: Magnitude of acceleration should be reported over telemetry so
	 * ACC_SCALE_WEIGHT can be more accurately determined.
	 */
	#ifdef ACC_SCALE_WEIGHT
	acc_scale = (1.0 - MIN(1.0, ACC_SCALE_WEIGHT * ABS(acc_scale - 1.0)));
	acc_weight = ACC_WEIGHT * acc_scale;
	#else
	acc_weight = ACC_WEIGHT;

	// Ignore accelerometer if it measures anything 0.5g past gravity.
	if (acc_scale > 1.5 || acc_scale < 0.5) {
		acc_weight = 0;
	}
	#endif // ACC_SCALE_WEIGHT

	/**
	 * Express K global unit vector in body frame as k_gb for use in drift
	 * correction (we need K to be described in the body frame because gravity
	 * is measured by the accelerometer in the body frame). Technically we
	 * could just create a transpose of dcm_gyro, but since we don't (yet) have
	 * a magnetometer, we don't need the first two rows of the transpose. This
	 * saves a few clock cycles.
	 */
	for (i=0; i<3; i++) {
		k_gb[i] = dcm_gyro[i][2];
	}

	/**
	 * Calculate gyro drift correction rotation vector w_a, which will be used
	 * later to bring KB closer to the gravity vector (i.e., the negative of
	 * the K vector). Although we do not explicitly negate the gravity vector,
	 * the cross product below produces a rotation vector that we can later add
	 * to the angular displacement vector to correct for gyro drift in the
	 * X and Y axes. Note we negate w_a because our acceleration vector is
	 * actually the negative of our gravity vector.
	 */
	v_crossp(k_gb, v_acc, w_a);
	v_scale(w_a, -1, w_a);
	#endif // ACC_WEIGHT

	/**
	 * Magnetometer
	 *     Frame of reference: body
	 *     Units: N/A
	 *     Purpose: Measure the magnetic north vector v_mag with components
	 *              codirectional with the body's i, j, and k vectors.
	 */
	#ifdef MAG_WEIGHT
	// Express J global unit vectory in body frame as j_gb.
	for (i=0; i<3; i++) {
		j_gb[i] = dcm_gyro[i][1];
	}

	// Calculate yaw drift correction vector w_m.
	v_crossp(j_gb, v_mag, w_m);
	#endif // MAG_WEIGHT

	/**
	 * Gyroscope
	 *     Frame of reference: body
	 *     Units: rad/s
	 *     Purpose: Measure the rotation rate of the body about the body's i,
	 *              j, and k axes.
	 * ========================================================================
	 * Scale v_gyr by elapsed time (in seconds) to get angle w*dt in radians,
	 * then compute weighted average with the accelerometer and magnetometer
	 * correction vectors to obtain final w*dt.
	 * TODO: This is still not exactly correct.
	 */
	for (i=0; i<3; i++) {
		w_dt[i] = v_gyr[i] * dt;

		#ifdef ACC_WEIGHT
		w_dt[i] += acc_weight * w_a[i];
		#endif // ACC_WEIGHT

		#ifdef MAG_WEIGHT
		w_dt[i] += MAG_WEIGHT * w_m[i];
		#endif // MAG_WEIGHT
	}

	/**
	 * Direction Cosine Matrix
	 *     Frame of reference: global
	 *     Units: None (unit vectors)
	 *     Purpose: Calculate the components of the body's i, j, and k unit
	 *              vectors in the global frame of reference.
	 * ========================================================================
	 * Skew the rotation vector and sum appropriate components by combining the
	 * skew symmetric matrix with the identity matrix. The math can be
	 * summarized as follows:
	 *
	 * All of this is calculated in the body frame. If w is the angular
	 * velocity vector, let w_dt (w*dt) be the angular displacement vector of
	 * the DCM over a time interval dt. Let w_dt_i, w_dt_j, and w_dt_k be the
	 * components of w_dt codirectional with the i, j, and k unit vectors,
	 * respectively. Also, let dr be the linear displacement vector of the DCM
	 * and dr_i, dr_j, and dr_k once again be the i, j, and k components,
	 * respectively.
	 *
	 * In very small dt, certain vectors approach orthogonality, so we can
	 * assume that (draw this out for yourself!):
	 *
	 *     dr_x = <    0,  dw_k, -dw_j>,
	 *     dr_y = <-dw_k,     0,  dw_i>, and
	 *     dr_z = < dw_j, -dw_i,     0>,
	 *
	 * which can be expressed as the rotation matrix:
	 *
	 *          [     0  dw_k -dw_j ]
	 *     dr = [ -dw_k     0  dw_i ]
	 *          [  dw_j -dw_i     0 ].
	 *
	 * This can then be multiplied by the current DCM and added to the current
	 * DCM to update the DCM. To minimize the number of calculations performed
	 * by the processor, however, we can combine the last two steps by
	 * combining dr with the identity matrix to produce:
	 *
	 *              [     1  dw_k -dw_j ]
	 *     dr + I = [ -dw_k     1  dw_i ]
	 *              [  dw_j -dw_i     1 ],
	 *
	 * which we multiply with the current DCM to produce the updated DCM
	 * directly.
	 *
	 * It may be helpful to read the Wikipedia pages on cross products and
	 * rotation representation.
	 */
	dcm_d[0][0] =        1;
	dcm_d[0][1] =  w_dt[2];
	dcm_d[0][2] = -w_dt[1];
	dcm_d[1][0] = -w_dt[2];
	dcm_d[1][1] =        1;
	dcm_d[1][2] =  w_dt[0];
	dcm_d[2][0] =  w_dt[1];
	dcm_d[2][1] = -w_dt[0];
	dcm_d[2][2] =        1;

	// Multiply the current DCM with the change in DCM and update.
	m_product(dcm_d, dcm_gyro, dcm_gyro);

	// Remove any distortions introduced by the small-angle approximations.
	orthonormalize(dcm_gyro);

	// Apply rotational offset (in case IMU is not installed orthogonally to
	// the airframe).
	dcm_offset[0][0] =              1;
	dcm_offset[0][1] =              0;
	dcm_offset[0][2] = -trim_angle[1];
	dcm_offset[1][0] =              0;
	dcm_offset[1][1] =              1;
	dcm_offset[1][2] =  trim_angle[0];
	dcm_offset[2][0] =  trim_angle[1];
	dcm_offset[2][1] = -trim_angle[0];
	dcm_offset[2][2] =              1;
	m_product(dcm_offset, dcm_gyro, dcm_out);
}
예제 #8
0
/**
 * Test matrix product.
 */
void test_m_product()
{
	// multiply two vectors, A * B
	precision_t data_A1[][4] = {
		{ 1, 1, 0, 0 }
	};
	precision_t data_B1[][1] = {
		{ 1 },
		{ 2 },
		{ 3 },
		{ 4 }
	};

	matrix_t *A = m_initialize(1, 4);
	matrix_t *B = m_initialize(4, 1);

	fill_matrix_data(A, data_A1);
	fill_matrix_data(B, data_B1);

	matrix_t *C = m_product(A, B);

	printf("A = \n");
	m_fprint(stdout, A);
	printf("B = \n");
	m_fprint(stdout, B);

	printf("A * B = \n");
	m_fprint(stdout, C);
	m_free(C);

	// multiply two vectors, B * A
	C = m_product(B, A);

	printf("B * A = \n");
	m_fprint(stdout, C);
	m_free(C);

	m_free(A);
	m_free(B);

	// multiply two arrays
	precision_t data_A2[][3] = {
		{ 1, 3, 5 },
		{ 2, 4, 7 }
	};
	precision_t data_B2[][3] = {
		{ -5, 8, 11 },
		{  3, 9, 21 },
		{  4, 0,  8 }
	};

	A = m_initialize(2, 3);
	B = m_initialize(3, 3);

	fill_matrix_data(A, data_A2);
	fill_matrix_data(B, data_B2);

	C = m_product(A, B);

	printf("A = \n");
	m_fprint(stdout, A);
	printf("B = \n");
	m_fprint(stdout, B);

	printf("A * B = \n");
	m_fprint(stdout, C);

	m_free(A);
	m_free(B);
	m_free(C);
}