天天看點

KNN近鄰算法預測愛的程度

基本上把一些點都注釋了,使用的原始資料是在網上找的      
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import operator
from os import listdir
# 設定在圖像中可以使用中文
from matplotlib.font_manager import FontProperties

font_set = FontProperties(fname=r'simsun.ttc', size=15)


def file_matrix(filename):
    """處理檔案内容,輸出處理成矩陣和類标簽向量"""
    fr = open(filename)
    fr1 = np.genfromtxt(filename, delimiter='\t', dtype=str, skip_header=0)
    # 每一行對象
    # print(fr1)
    array_lines = fr.readlines()
    # 總行數
    number_oflines = len(array_lines)
    # print(arrayOlines)
    # print(number_oflines)
    # 傳回一個給定形狀和類型的用0填充的數組
    # 參數:shape:形狀,dtype:可選參數,預設numpy.float64
    # order:可選,c代表行優先,f代表列優先
    return_mat = np.zeros((number_oflines, 3))
    class_label_vector = []
    index = 0
    for line in array_lines:
        # 移除每行開頭結尾的空格
        line = line.strip()
        # 切割字元串
        list_fromline = line.split('\t')
        # print(list_fromline)
        # 替換掉為0的資料
        return_mat[index, :] = list_fromline[0:3]
        # print(return_mat[index,:])
        # 将航班号存儲到清單中
        class_label_vector.append(int(list_fromline[-1]))
        index += 1
    return return_mat, class_label_vector


def matplotlib_(data):
    # 利用原始資料制作散點圖
    # 建立一個名為figure的畫圖視窗
    fig = plt.figure()
    # 添加子圖,111是預設參數,用來設定大小
    ax = fig.add_subplot(111)
    # 在子圖中畫scatter散點圖
    ax.scatter(data[:, 0], data[:, 1])
    # 設定可以顯示中文字型
    ax.set_ylabel(u'看電影的次數', fontproperties=font_set)
    ax.set_xlabel(u'玩視訊遊戲所耗的時間百分比', fontproperties=font_set)
    plt.show()


def auto_norm(dataset):
    """在原始資料的繼承上歸一化資料"""
    # 取出矩陣中最小的數,參數0使得取得的從列中取出最小值
    min_vals = dataset.min(0)
    # print(min_vals)
    # 取出矩陣中最大的數
    max_vals = dataset.max(0)
    ranges = max_vals - min_vals
    # 用0來填充矩陣
    norm_dataset = np.zeros(np.shape(dataset))
    # print(norm_dataset)
    # 取出行數
    m = dataset.shape[0]
    # print(m)
    # 歸一化公式:n e w V a l u e = {o l d V a l u e - m i n ) / (max-min)
    # np.tile将min_vals 這個矩陣的列複制m次
    norm_dataset = dataset - np.tile(min_vals, (m, 1))
    norm_dataset = norm_dataset / np.tile(ranges, (m, 1))
    return norm_dataset, ranges, min_vals


def classify0(inX, dataSet, labels, k):
    # 用來測試的行數,inx 目前一行矩陣,dataset用來測試的資料(後500行),labels分類結果,k是取前幾個值來預判
    dataSetSize = dataSet.shape[0]
    # 複制目前行數,在減去以前求得的最小值
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    # 平方
    sqDiffMat = diffMat ** 2
    # 求和
    sqDistances = sqDiffMat.sum(axis=1)
    # 根号處理
    distances = sqDistances ** 0.5
    # y|{0 - 67)2 + (20 000 - 32 000)2 + (1 • 1 — 0.1)2
    # argsort()函數是将x中的元素從小到大排列,提取其對應的index(索引),然後輸出到sortedDistIndicies
    sortedDistIndicies = distances.argsort()
    classCount = {}
    for i in range(k):
        # 取出與目前值誤差最小的3個值,來作為預測的結果
        voteIlabel = labels[sortedDistIndicies[i]]
        # 生成字典鍵,預設值為0
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    # py2和py3中字典的處理方式不同,3中是items(),reverse,預設是flase,由小到大,True由大大小,
    # key是選取value來判斷,寫成lambda item:item[0]結果一樣,可以接受的是一個函數
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    # 傳回結果中出現次數多的那個當結果
    return sortedClassCount[0][0]


def dating_classtest():
    # 分類器測試
    # 用來預測的原始資料
    horario = 0.5
    # 初始化資料
    data, data_list = file_matrix('datingTestSet2.txt')
    norm_dataset, ranges, min_vals = auto_norm(data)

    # 取行
    m = norm_dataset.shape[0]
    num_test_vecs = int(m * horario)
    # 初始化錯誤次數
    error_count = 0.0
    for i in range(num_test_vecs):
        # 調用classify0判斷預測結果
        class_ifier_result = classify0(norm_dataset[i, :], norm_dataset[num_test_vecs:m, :], data_list[num_test_vecs:m],
                                       3)
        print('正确結果是%d,預測的是%d' % (class_ifier_result, data_list[i]))
        if (class_ifier_result != data_list[i]):
            error_count += 1
    print("這次預測的正确率是%.2f%%" % ((1-(error_count) / float(num_test_vecs))*100))


data,list1 = file_matrix('datingTestSet2.txt')

matplotlib_(data)
# norm_dataset,ranges,c = auto_norm(data)
# print(a)
# dating_classtest()
def classify_person():
    result_list = ['一點點','很喜歡','愛']
    ff_miles = float(input("請輸入一年的出差裡數:"))
    peroent_tabs = float(input("玩視訊遊戲所耗的時間百分比:"))
    ice_creame = float(input("請輸入兩個人一起看電影的次數:"))
    data, data_list = file_matrix('datingTestSet2.txt')
    norm_dataset, ranges, min_vals = auto_norm(data)
    in_arr = np.array([ff_miles,peroent_tabs,ice_creame])
    # print(in_arr)
    # print(type(peroent_tabs))
    # print(type(min_vals))
    # print(type(ranges))
    data1 = (in_arr-min_vals)/ranges
    classifier_result = classify0(data1,norm_dataset,data_list,3)
    print("喜歡的程度:",result_list[classifier_result-1])

# classify_person()      
KNN近鄰算法預測愛的程度
KNN近鄰算法預測愛的程度

繼續閱讀