M-Fold Cross Validation Точность Просчет без ошибок - PullRequest
0 голосов
/ 18 апреля 2019

Я выполняю m-кратную перекрестную проверку с помощью собственной пользовательской функции k-ближайшего соседа, и мои значения точности не только редко меняются для введенных обучающих и тестовых наборов, но и общая точность довольно низкая. Я тестирую свои функции в наборе данных "fglass.dat", причем документ "fglass.grp" представляет собой используемый для определения того, какие столбцы должны быть удалены (m-кратно) и используется в качестве набора тестов для KNN. И хотя я считаю, что моя функция «createFolds», которая отвечает за извлечение этого тестового столбца, работает, я не знаю, как определить правильные типы классов в моем коде в моей функции KNN. Как я должен определить тип класса для "glass.dat" для всех 214 строк? «fragArray» - это данные «fglass.dat», а «iterArray» - данные «fglass.grp».

Используя выходные данные #Debugging, одни и те же несколько индексов trainSample из моего евклидова уравнения расстояния обнаруживаются почти все время, что приводит к тому, что typeIndex всегда одинаков для каждого прогона. Это приводит к тому, что вычисление цикла точности работает только для этого одного типа класса по сравнению со всеми другими типами классов (например, если typeIndex = 5 для всех testSamples, тогда все индексы с 1 по 7, которые не являются 5, неверны), что приводит к такая же плохая точность. Итак, из того, что я могу сказать, проблема в том, что «typeIndex» никогда не меняется.

def EuclidCalc(data1, data2, length):

    distance = 0

    for point in range(length):
        #for this project, data1 (test data) has only 1 element here
        distance += math.pow(data1 - data2[point], 2)
    distance = math.sqrt(distance)

    return distance

def KNNPredict(trainFold, testFold, classInfo, k):

    fragTypes = [] #array to store all the calculated fragment types

    totalCorrect = 0 #used for accuracy

    runCount = 0

    #for all test samples in the test fold
    for testSample in range(len(testFold)):

        #Attempt to calculate the correct fragment type within this for loop

        # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        # create distance and (k) nearest neighbors arrays
        distances = []
        nearestNeighbors = [] #length = k

        for trainSample in range(len(trainFold)):
            #find the Euclidean distance between samples

            distance = EuclidCalc(testFold[testSample], trainFold[trainSample], len(trainFold[trainSample]))

            distances.append([distance, trainSample]) #record the current sample with its corresponding distance

        #sort distances array in ascending order
        distances = sorted(distances)

        if(runCount < 1):
            print("3 closest distances: ", distances[0:3])

        #find the (k) nearest neighbors in the trainFold array
        for kNeighbor in range(k):
            neighborIndex = distances[kNeighbor][1]

            nearestNeighbors.append(classInfo[neighborIndex]) #record the found nearest neighbor type

        if(runCount < 1):
            print("neigbhors: ", nearestNeighbors)

        classVotes = {} #create dictionary for the votes, this is more flexible for the number of class types

        for neighbor in range(len(nearestNeighbors)):
            vote = nearestNeighbors[neighbor] #return classType

            #either add vote to existing collection of the same class type,
            #or create a new class vote type
            if vote in classVotes: #if class type votes were already done
                classVotes[vote] = classVotes[vote] + 1 #add another vote to the same class type
            else:
                classVotes[vote] = 1 #create a new tally of votes for this class type

        if(runCount < 1):
            print("all classes with their number of votes: ", classVotes)

        typeIndex = max(classVotes.keys(), key=(lambda keyVal: classVotes[keyVal])) #determine which type got the most votes

        if(runCount < 1):
            print("chosen type: ", typeIndex)

            input("Press Enter to continue")

        #record calculated fragment type
        fragTypes.append(typeIndex)

        runCount = runCount + 1

    for fragment in range(len(fragTypes)):
        correctType = int(classInfo[fragment]) #find the correct type for each test fold fragment

        #print("correct type: ", correctType)
        #print("found type: ", fragTypes[fragment])

        #input("Press Enter to continue")

        if (int(fragTypes[fragment]) == correctType):
            totalCorrect = totalCorrect + 1

    accuracy = float(totalCorrect/float(len(classInfo))) #convert accuracy to a float between 0 and 1

    return accuracy

def createFolds(fragArray, iterArray):

    iterNum = 1 #iteration number in iterArray
    randomClass = 0 #the type class associated with the iteration

    extractArray = fragArray #use this array to remove the test column

    folds = [] #store all train and test folds here

    #while all iteration types are still being found
    while (iterNum < len(iterArray) + 1):

        #for all iterations
        for iterationVal in range(len(iterArray)):
            if(int(iterArray[iterationVal][1]) == iterNum): #if the iterations match
                randomClass = iterArray[iterationVal][0] #get the "random" class column index associated with the iteration

        testSet = [row[randomClass - 1] for row in fragArray] #separate the test class column from fragArray

        trainSet = np.delete(extractArray, (randomClass - 1), 1) #remove the test class column from extractArray
        trainSet = trainSet.tolist()

        folds.append([trainSet, testSet]) #save training and test arrays as a fold

        extractArray = fragArray #reset extract array
        iterNum = iterNum + 1

    return folds

def KNNCrossCalc(fragArray, iterArray, k):

    classInfo = [row[len(fragArray[0]) - 1] for row in fragArray]

    #return training and test dataset folds as a single total fold
    folds = createFolds(fragArray, iterArray)

    #print(np.array(indexArray).shape)

    #To get the training set of each fold: folds[fold of choice][0]
    #To get the test set of each fold: folds[fold of choice][1]

    #DEBUGGING!!!!!!!!!!!!!!!
    #print(np.array(folds[0][0]).shape) = (214, 9)
    #print(np.array(folds[0][1]).shape) = (214, )

    totalAccuracy = 0

    for foldNum in range(len(folds)): #for each collection of folds

        #find the accuracy for each fold using KNN
        accuracy = KNNPredict(folds[foldNum][0], folds[foldNum][1], classInfo, k)
        #print("Fold ", (foldNum + 1), " accuracy: ", (accuracy * 100), "%")

        #accumulate all accuracy calculations in totalAccuracy
        totalAccuracy = totalAccuracy + accuracy

    #calculate the average accuracy for this run for all folds
    averageAccuracy = float(totalAccuracy / len(folds))
    print("\nAverage accuracy for all folds: ", (averageAccuracy* 100), "%")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...