我希望这里有人能帮我:
我试图实现一个神经网络来寻找数据簇,这是一个二维的簇我试图遵循wikipedia中描述的标准算法:我为每个数据点寻找最小距离,并向数据点更新该神经元的权重。当总距离足够小时,我就停止这样做。
我的结果是找到了大多数的星团,但是在一个视图上是错误的,虽然它计算了一个永久距离,但它不再会聚。我的错误在哪里?
typedef struct{
double x;
double y;
}Data;
typedef struct{
double x;
double y;
}Neuron;
typedef struct{
size_t numNeurons;
Neuron* neurons;
}Network;
int main(void){
srand(time(NULL));
Data trainingData[1000];
size_t sizeTrainingData = 0;
size_t sizeClasses = 0;
Network network;
getData(trainingData, &sizeTrainingData, &sizeClasses);
initializeNetwork(&network, sizeClasses);
normalizeData(trainingData, sizeTrainingData);
train(&network, trainingData, sizeTrainingData);
return 0;
}
void train(Network* network, Data trainingData[], size_t sizeTrainingData){
for(int epoch=0; epoch<TRAINING_EPOCHS; ++epoch){
double learningRate = getLearningRate(epoch);
double totalDistance = 0;
for(int i=0; i<sizeTrainingData; ++i){
Data currentData = trainingData[i];
int winningNeuron = 0;
totalDistance += findWinningNeuron(network, currentData, &winningNeuron);
//update weight
network->neurons[i].x += learningRate * (currentData.x - network->neurons[i].x);
network->neurons[i].y += learningRate * (currentData.y - network->neurons[i].y);
}
if(totalDistance<MIN_TOTAL_DISTANCE) break;
}
}
double getLearningRate(int epoch){
return LEARNING_RATE * exp(-log(LEARNING_RATE/LEARNING_RATE_MIN_VALUE)*((double)epoch/TRAINING_EPOCHS));
}
double findWinningNeuron(Network* network, Data data, int* winningNeuron){
double smallestDistance = 9999;
for(unsigned int currentNeuronIndex=0; currentNeuronIndex<network->numNeurons; ++currentNeuronIndex){
Neuron neuron = network->neurons[currentNeuronIndex];
double distance = sqrt(pow(data.x-neuron.x,2)+pow(data.y-neuron.y,2));
if(distance<smallestDistance){
smallestDistance = distance;
*winningNeuron = currentNeuronIndex;
}
}
return smallestDistance;
}
initializeNetwork(...)
以-1和1范围内的随机权重启动所有神经元。normalizeData(...)
以某种方式规格化,因此最大值为1。例如:
如果我给网络提供大约50个(标准化的)数据点,这些数据点分成3个簇,那么剩下的
totaldistance
保持在大约7.3。当我检查神经元的位置时,它应该代表了簇的中心,两个是完美的,一个在簇的边缘。不是应该用算法把它移到中心吗?我重复了好几次算法,结果总是相似的(在完全相同的错误点上) 最佳答案
你的代码看起来不像LVQ,特别是你从来没有使用过获胜的神经元,而你应该只移动这个
void train(Network* network, Data trainingData[], size_t sizeTrainingData){
for(int epoch=0; epoch<TRAINING_EPOCHS; ++epoch){
double learningRate = getLearningRate(epoch);
double totalDistance = 0;
for(int i=0; i<sizeTrainingData; ++i){
Data currentData = trainingData[i];
int winningNeuron = 0;
totalDistance += findWinningNeuron(network, currentData, &winningNeuron);
//update weight
network->neurons[i].x += learningRate * (currentData.x - network->neurons[i].x);
network->neurons[i].y += learningRate * (currentData.y - network->neurons[i].y);
}
if(totalDistance<MIN_TOTAL_DISTANCE) break;
}
}
你要移动的神经元在
winningNeuron
中,但是你更新了第i
个神经元,在那里i
实际上在训练样本上重复,我很惊讶你没有从你的记忆中掉下来(网络->神经元应该小于SizeTrainingData)。我想你的意思是void train(Network* network, Data trainingData[], size_t sizeTrainingData){
for(int epoch=0; epoch<TRAINING_EPOCHS; ++epoch){
double learningRate = getLearningRate(epoch);
double totalDistance = 0;
for(int i=0; i<sizeTrainingData; ++i){
Data currentData = trainingData[i];
int winningNeuron = 0;
totalDistance += findWinningNeuron(network, currentData, &winningNeuron);
//update weight
network->neurons[winningNeuron].x += learningRate * (currentData.x - network->neurons[winningNeuron].x);
network->neurons[winningNeuron].y += learningRate * (currentData.y - network->neurons[winningNeuron].y);
}
if(totalDistance<MIN_TOTAL_DISTANCE) break;
}
}
关于c - ANN:学习 vector 量化无效,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34415829/