⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fann_cascade.c

📁 python 神经网络 数据挖掘 python实现的神经网络算法
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * but there is an empty place between the real neurons and the candidate neurons,
	 * so that it will be possible to make room when the chosen candidate are copied in
	 * on the desired place.
	 */
	unsigned int neurons_to_allocate, connections_to_allocate;
	unsigned int num_candidates = fann_get_cascade_num_candidates(ann);
	unsigned int num_neurons = ann->total_neurons + num_candidates + 1;
	unsigned int candidate_connections_in = ann->total_neurons - ann->num_output;
	unsigned int candidate_connections_out = ann->num_output;

	/* the number of connections going into a and out of a candidate is
	 * ann->total_neurons */
	unsigned int num_connections =
		ann->total_connections + (ann->total_neurons * (num_candidates + 1));
	unsigned int first_candidate_connection = ann->total_connections + ann->total_neurons;
	unsigned int first_candidate_neuron = ann->total_neurons + 1;
	unsigned int connection_it, i, j, k, candidate_index;
	struct fann_neuron *neurons;
	fann_type initial_slope;
	
	/* First make sure that there is enough room, and if not then allocate a
	 * bit more so that we do not need to allocate more room each time.
	 */
	if(num_neurons > ann->total_neurons_allocated)
	{
		/* Then we need to allocate more neurons
		 * Allocate half as many neurons as already exist (at least ten)
		 */
		neurons_to_allocate = num_neurons + num_neurons / 2;
		if(neurons_to_allocate < num_neurons + 10)
		{
			neurons_to_allocate = num_neurons + 10;
		}

		if(fann_reallocate_neurons(ann, neurons_to_allocate) == -1)
		{
			return -1;
		}
	}

	if(num_connections > ann->total_connections_allocated)
	{
		/* Then we need to allocate more connections
		 * Allocate half as many connections as already exist
		 * (at least enough for ten neurons)
		 */
		connections_to_allocate = num_connections + num_connections / 2;
		if(connections_to_allocate < num_connections + ann->total_neurons * 10)
		{
			connections_to_allocate = num_connections + ann->total_neurons * 10;
		}

		if(fann_reallocate_connections(ann, connections_to_allocate) == -1)
		{
			return -1;
		}
	}

	/* Set the neurons.
	 */
	connection_it = first_candidate_connection;
	neurons = ann->first_layer->first_neuron;
	candidate_index = first_candidate_neuron;

	for(i = 0; i < ann->cascade_activation_functions_count; i++)
	{
		for(j = 0; j < ann->cascade_activation_steepnesses_count; j++)
		{
			for(k = 0; k < ann->cascade_num_candidate_groups; k++)
			{
				/* TODO candidates should actually be created both in
				 * the last layer before the output layer, and in a new layer.
				 */
				neurons[candidate_index].value = 0;
				neurons[candidate_index].sum = 0;
				
				neurons[candidate_index].activation_function =
					ann->cascade_activation_functions[i];
				neurons[candidate_index].activation_steepness =
					ann->cascade_activation_steepnesses[j];
				
				neurons[candidate_index].first_con = connection_it;
				connection_it += candidate_connections_in;
				neurons[candidate_index].last_con = connection_it;
				/* We have no specific pointers to the output weights, but they are
				 * available after last_con */
				connection_it += candidate_connections_out;
				ann->train_errors[candidate_index] = 0;
				candidate_index++;
			}
		}
	}

	/* Now randomize the weights and zero out the arrays that needs zeroing out.
	 */
#ifdef CASCADE_DEBUG_FULL
	printf("random cand weight [%d ... %d]\n", first_candidate_connection, num_connections - 1);
#endif
	if(ann->training_algorithm == FANN_TRAIN_RPROP)
	{
		initial_slope = ann->rprop_delta_zero;
	}
	else
	{
		initial_slope = 0.0;
	}
	for(i = first_candidate_connection; i < num_connections; i++)
	{
		ann->weights[i] = fann_random_weight();
		/*ann->weights[i] = fann_rand(-0.25,0.25);*/
		ann->train_slopes[i] = 0;
		ann->prev_steps[i] = 0;
		ann->prev_train_slopes[i] = initial_slope;
	}

	return 0;
}

int fann_train_candidates(struct fann *ann, struct fann_train_data *data)
{
	fann_type best_cand_score = 0.0;
	fann_type target_cand_score = 0.0;
	fann_type backslide_cand_score = -1.0e20f;
	unsigned int i;
	unsigned int max_epochs = ann->cascade_max_cand_epochs;
	unsigned int stagnation = max_epochs;

	if(ann->cascade_candidate_scores == NULL)
	{
		ann->cascade_candidate_scores =
			(fann_type *) malloc(fann_get_cascade_num_candidates(ann) * sizeof(fann_type));
		if(ann->cascade_candidate_scores == NULL)
		{
			fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
			return 0;
		}
	}

	for(i = 0; i < max_epochs; i++)
	{
		best_cand_score = fann_train_candidates_epoch(ann, data);

		if(best_cand_score / ann->MSE_value > ann->cascade_candidate_limit)
		{
#ifdef CASCADE_DEBUG
			printf("above candidate limit %f/%f > %f", best_cand_score, ann->MSE_value,
				   ann->cascade_candidate_limit);
#endif
			return i + 1;
		}

		if((best_cand_score > target_cand_score) || (best_cand_score < backslide_cand_score))
		{
#ifdef CASCADE_DEBUG_FULL
			printf("Best candidate score %f, real score: %f\n", ann->MSE_value - best_cand_score,
				   best_cand_score);
			/* printf("best_cand_score=%f, target_cand_score=%f, backslide_cand_score=%f, stagnation=%d\n", best_cand_score, target_cand_score, backslide_cand_score, stagnation); */
#endif

			target_cand_score = best_cand_score * (1.0f + ann->cascade_candidate_change_fraction);
			backslide_cand_score = best_cand_score * (1.0f - ann->cascade_candidate_change_fraction);
			stagnation = i + ann->cascade_candidate_stagnation_epochs;
		}

		/* No improvement in allotted period, so quit */
		if(i >= stagnation)
		{
#ifdef CASCADE_DEBUG
			printf("Stagnation with %d epochs, best candidate score %f, real score: %f\n", i + 1,
				   ann->MSE_value - best_cand_score, best_cand_score);
#endif
			return i + 1;
		}
	}

#ifdef CASCADE_DEBUG
	printf("Max epochs %d reached, best candidate score %f, real score: %f\n", max_epochs,
		   ann->MSE_value - best_cand_score, best_cand_score);
#endif
	return max_epochs;
}

void fann_update_candidate_slopes(struct fann *ann)
{
	struct fann_neuron *neurons = ann->first_layer->first_neuron;
	struct fann_neuron *first_cand = neurons + ann->total_neurons + 1;
	struct fann_neuron *last_cand = first_cand + fann_get_cascade_num_candidates(ann);
	struct fann_neuron *cand_it;
	unsigned int i, j, num_connections;
	unsigned int num_output = ann->num_output;
	fann_type max_sum, cand_sum, activation, derived, error_value, diff, cand_score;
	fann_type *weights, *cand_out_weights, *cand_slopes, *cand_out_slopes;
	fann_type *output_train_errors = ann->train_errors + (ann->total_neurons - ann->num_output);

	for(cand_it = first_cand; cand_it < last_cand; cand_it++)
	{
		cand_score = ann->cascade_candidate_scores[cand_it - first_cand];
		error_value = 0.0;

		/* code more or less stolen from fann_run to fast forward pass
		 */
		cand_sum = 0.0;
		num_connections = cand_it->last_con - cand_it->first_con;
		weights = ann->weights + cand_it->first_con;

		/* unrolled loop start */
		i = num_connections & 3;	/* same as modulo 4 */
		switch (i)
		{
			case 3:
				cand_sum += weights[2] * neurons[2].value;
			case 2:
				cand_sum += weights[1] * neurons[1].value;
			case 1:
				cand_sum += weights[0] * neurons[0].value;
			case 0:
				break;
		}

		for(; i != num_connections; i += 4)
		{
			cand_sum +=
				weights[i] * neurons[i].value +
				weights[i + 1] * neurons[i + 1].value +
				weights[i + 2] * neurons[i + 2].value + weights[i + 3] * neurons[i + 3].value;
		}
		/*
		 * for(i = 0; i < num_connections; i++){
		 * cand_sum += weights[i] * neurons[i].value;
		 * }
		 */
		/* unrolled loop end */

		max_sum = 150/cand_it->activation_steepness;
		if(cand_sum > max_sum)
			cand_sum = max_sum;
		else if(cand_sum < -max_sum)
			cand_sum = -max_sum;
		
		activation =
			fann_activation(ann, cand_it->activation_function, cand_it->activation_steepness,
							cand_sum);
		/* printf("%f = sigmoid(%f);\n", activation, cand_sum); */

		cand_it->sum = cand_sum;
		cand_it->value = activation;

		derived = fann_activation_derived(cand_it->activation_function,
										  cand_it->activation_steepness, activation, cand_sum);

		/* The output weights is located right after the input weights in
		 * the weight array.
		 */
		cand_out_weights = weights + num_connections;

		cand_out_slopes = ann->train_slopes + cand_it->first_con + num_connections;
		for(j = 0; j < num_output; j++)
		{
			diff = (activation * cand_out_weights[j]) - output_train_errors[j];
#ifdef CASCADE_DEBUG_FULL
			/* printf("diff = %f = (%f * %f) - %f;\n", diff, activation, cand_out_weights[j], output_train_errors[j]); */
#endif
			cand_out_slopes[j] -= 2.0f * diff * activation;
#ifdef CASCADE_DEBUG_FULL
			/* printf("cand_out_slopes[%d] <= %f += %f * %f;\n", j, cand_out_slopes[j], diff, activation); */
#endif
			error_value += diff * cand_out_weights[j];
			cand_score -= (diff * diff);
#ifdef CASCADE_DEBUG_FULL
			/* printf("cand_score[%d][%d] = %f -= (%f * %f)\n", cand_it - first_cand, j, cand_score, diff, diff); */

			printf("cand[%d]: error=%f, activation=%f, diff=%f, slope=%f\n", cand_it - first_cand,
				   output_train_errors[j], (activation * cand_out_weights[j]), diff,
				   -2.0 * diff * activation);
#endif
		}

		ann->cascade_candidate_scores[cand_it - first_cand] = cand_score;
		error_value *= derived;

		cand_slopes = ann->train_slopes + cand_it->first_con;
		for(i = 0; i < num_connections; i++)
		{
			cand_slopes[i] -= error_value * neurons[i].value;
		}
	}
}

void fann_update_candidate_weights(struct fann *ann, unsigned int num_data)
{
	struct fann_neuron *first_cand = (ann->last_layer - 1)->last_neuron + 1;	/* there is an empty neuron between the actual neurons and the candidate neuron */
	struct fann_neuron *last_cand = first_cand + fann_get_cascade_num_candidates(ann) - 1;

	switch (ann->training_algorithm)
	{
		case FANN_TRAIN_RPROP:
			fann_update_weights_irpropm(ann, first_cand->first_con,
										last_cand->last_con + ann->num_output);
			break;
		case FANN_TRAIN_QUICKPROP:
			fann_update_weights_quickprop(ann, num_data, first_cand->first_con,
										  last_cand->last_con + ann->num_output);
			break;
		case FANN_TRAIN_BATCH:
		case FANN_TRAIN_INCREMENTAL:
			fann_error((struct fann_error *) ann, FANN_E_CANT_USE_TRAIN_ALG);
			break;
	}
}

fann_type fann_train_candidates_epoch(struct fann *ann, struct fann_train_data *data)
{
	unsigned int i, j;
	unsigned int best_candidate;
	fann_type best_score;
	unsigned int num_cand = fann_get_cascade_num_candidates(ann);
	fann_type *output_train_errors = ann->train_errors + (ann->total_neurons - ann->num_output);
	struct fann_neuron *output_neurons = (ann->last_layer - 1)->first_neuron;

	for(i = 0; i < num_cand; i++)
	{
		/* The ann->MSE_value is actually the sum squared error */
		ann->cascade_candidate_scores[i] = ann->MSE_value;
	}
	/*printf("start score: %f\n", ann->MSE_value); */

	for(i = 0; i < data->num_data; i++)
	{
		fann_run(ann, data->input[i]);

		for(j = 0; j < ann->num_output; j++)
		{
			/* TODO only debug, but the error is in opposite direction, this might be usefull info */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -