public LVQ3x(List <float[]>[] trainData, List <float[]>[] testData, float learningRate, int codebookVectorCount, int iterationCount, string name, float window, float breaker, float decay) : base(trainData, testData, learningRate, codebookVectorCount, iterationCount, name, decay) { s = (1 - window) / (1 + window); this.breaker = breaker; distances = new CodebookDistance[classCount * codebookVectorCount]; }
protected override void Train(float[] data, int trueClassIndex) { for (int i = 0; i < classCount; i++) { for (int j = 0; j < codebookVectorCount; j++) { distances[i * codebookVectorCount + j] = new CodebookDistance(i, j, Distance(codebookVector[i, j], data), trueClassIndex == i); } } Array.Sort(distances, (d1, d2) => d1.distance.CompareTo(d2.distance)); float min = float.MaxValue; float max = float.MinValue; for (int i = 0; i < classCount; i++) { minDistance[i] = distances[i]; if (max < distances[i].distance) { max = distances[i].distance; } if (min > distances[i].distance) { min = distances[i].distance; } } if (min / max > s) { bool sameClass = true; for (int i = 0; i < classCount; i++) { if (!minDistance[i].trueClass) { sameClass = false; break; } } for (int i = 0; i < classCount; i++) { if (!sameClass) { if (minDistance[i].trueClass) { for (int j = 0; j < mnistSize; j++) { codebookVector[minDistance[i].classIndex, minDistance[i].codebookIndex][j] += learningRate * (data[j] - codebookVector[minDistance[i].classIndex, minDistance[i].codebookIndex][j]); } } else { for (int j = 0; j < mnistSize; j++) { codebookVector[minDistance[i].classIndex, minDistance[i].codebookIndex][j] -= learningRate * (data[j] - codebookVector[minDistance[i].classIndex, minDistance[i].codebookIndex][j]); } } } else { for (int j = 0; j < mnistSize; j++) { codebookVector[minDistance[i].classIndex, minDistance[i].codebookIndex][j] += breaker * learningRate * (data[j] - codebookVector[minDistance[i].classIndex, minDistance[i].codebookIndex][j]); } } } } }