日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

k近邻算法原理c语言,实验二 K-近邻算法及应用

發布時間:2024/4/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 k近邻算法原理c语言,实验二 K-近邻算法及应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作業信息

一.【實驗目的】

理解K-近鄰算法原理,能實現算法K近鄰算法;

掌握常見的距離度量方法;

掌握K近鄰樹實現算法;

針對特定應用場景及數據,能應用K近鄰解決實際問題。

二.【實驗內容】

實現曼哈頓距離、歐氏距離、閔式距離算法,并測試算法正確性。

實現K近鄰樹算法;

針對iris數據集,應用sklearn的K近鄰算法進行類別預測。

針對iris數據集,編制程序使用K近鄰樹進行類別預測。

三.【實驗報告要求】

對照實驗內容,撰寫實驗過程、算法及測試結果;

代碼規范化:命名規則、注釋;

分析核心算法的復雜度;

查閱文獻,討論K近鄰的優缺點;

舉例說明K近鄰的應用場景。

四.【實驗結果及截圖】

import math

from itertools import combinations

def L(x, y, p=2):

# x1 = [1, 1], x2 = [5,1]

# 此處是定義閔氏距離的公式,x和y分別指數據的行和列,只有維數一致才進行計算,p表示當前進行的是什么運算

if len(x) == len(y) and len(x) > 1:

sum = 0

for i in range(len(x)):

sum += math.pow(abs(x[i] - y[i]), p)

return math.pow(sum, 1/p)

else:

return 0

# 課本例3.1

x1 = [1, 1]

x2 = [5, 1]

x3 = [4, 4]

# 分別在p=1-4的情況下,對x1與x2,x3的距離的計算,并輸出最小值

for i in range(1, 5):

r = { \'1-{}\'.format(c):L(x1, c, p=i) for c in [x2, x3]}

print(min(zip(r.values(), r.keys())))

# r此時為字典,values是距離的值,keys表示距離的端點

# 讀入iris數據集

# data

iris = load_iris()

df = pd.DataFrame(iris.data, columns=iris.feature_names)

df[\'label\'] = iris.target # 加入一列為分類標簽

df.columns = [\'sepal length\', \'sepal width\', \'petal length\', \'petal width\', \'label\']

# data = np.array(df.iloc[:100, [0, 1, -1]])

df

# 做iris散點圖,并根據長度進行分類,用0和1標記

plt.scatter(df[:50][\'sepal length\'], df[:50][\'sepal width\'], label=\'0\')

plt.scatter(df[50:100][\'sepal length\'], df[50:100][\'sepal width\'], label=\'1\')

plt.xlabel(\'sepal length\')

plt.ylabel(\'sepal width\')

plt.legend()

data = np.array(df.iloc[:100, [0, 1, -1]])#取出sepal長度、寬度和標簽對應列的數據

X, y = data[:,:-1], data[:,-1]#X為sepal length,sepal width y為標簽

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)# 將矩陣隨機劃分為訓練集和測試集

#定義KNN這個類

class KNN:

def __init__(self, X_train, y_train, n_neighbors=3, p=2):

"""

parameter: n_neighbors 臨近點個數

parameter: p 距離度量

"""

self.n = n_neighbors

self.p = p

self.X_train = X_train

self.y_train = y_train

# 計算出預測含有同一屬性的點

def predict(self, X):

# 取出n個點,放入空的列表,列表中存放預測點與訓練集點的距離及其對應標簽

knn_list = []

for i in range(self.n):

#np.linalg.norm 求范數

dist = np.linalg.norm(X - self.X_train[i], ord=self.p)

knn_list.append((dist, self.y_train[i]))

#依次取出訓練集中的點,選出其中n_neighbor個距離最大的點

#距離最小的點存在knn_list中

for i in range(self.n, len(self.X_train)):

\'\'\'

此處 max(num,key=lambda x: x[0])用法:

x:x[]字母可以隨意修改,求最大值方式按照中括號[]里面的維度,

[0]按照第一維,

[1]按照第二維

\'\'\'

max_index = knn_list.index(max(knn_list, key=lambda x: x[0]))

dist = np.linalg.norm(X - self.X_train[i], ord=self.p)

if knn_list[max_index][0] > dist:

knn_list[max_index] = (dist, self.y_train[i])

# 統計分類最多的點,確定預測數據的分類

knn = [k[-1] for k in knn_list]

#counter為計數器,按照標簽計數

count_pairs = Counter(knn)

#排序

max_count = sorted(count_pairs, key=lambda x:x)[-1]

return max_count

#預測的正確率

def score(self, X_test, y_test):

right_count = 0

n = 10

for X, y in zip(X_test, y_test):

label = self.predict(X)

if label == y:

right_count += 1

return right_count / len(X_test)

clf = KNN(X_train, y_train)

clf.score(X_test, y_test)

0.05

test_point = [6.0, 3.0]#預測點

print(\'Test Point: {}\'.format(clf.predict(test_point)))

Test Point:1.0

#預測點

plt.scatter(df[:50][\'sepal length\'], df[:50][\'sepal width\'], label=\'0\')

plt.scatter(df[50:100][\'sepal length\'], df[50:100][\'sepal width\'], label=\'1\')

#打印預測點

plt.plot(test_point[0], test_point[1], \'bo\', label=\'test_point\')

plt.xlabel(\'sepal length\')

plt.ylabel(\'sepal width\')

plt.legend()

from sklearn.neighbors import KNeighborsClassifier

clf_sk = KNeighborsClassifier()

clf_sk.fit(X_train, y_train)

clf_sk.score(X_test, y_test)

1.0

# kd-tree每個結點中主要包含的數據結構如下 class KdNode(object):

def __init__(self, dom_elt, split, left, right):

self.dom_elt = dom_elt # k維向量節點(k維空間中的一個樣本點)

self.split = split # 整數(進行分割維度的序號)

self.left = left # 該結點分割超平面左子空間構成的kd-tree

self.right = right # 該結點分割超平面右子空間構成的kd-tree

class KdTree(object):

def __init__(self, data):

k = len(data[0]) # 數據維度

def CreateNode(split, data_set): # 按第split維劃分數據集exset創建KdNode

if not data_set: # 數據集為空

return None

# key參數的值為一個函數,此函數只有一個參數且返回一個值用來進行比較

# operator模塊提供的itemgetter函數用于獲取對象的哪些維的數據,參數為需要獲取的數據在對象

#data_set.sort(key=itemgetter(split)) # 按要進行分割的那一維數據排序

data_set.sort(key=lambda x: x[split])

split_pos = len(data_set) // 2 # //為Python中的整數除法

median = data_set[split_pos] # 中位數分割點

split_next = (split + 1) % k # cycle coordinates

# 遞歸的創建kd樹

return KdNode(median, split,

CreateNode(split_next, data_set[:split_pos]), # 創建左子樹

CreateNode(split_next, data_set[split_pos + 1:])) # 創建右子樹

self.root = CreateNode(0, data) # 從第0維分量開始構建kd樹,返回根節點

# KDTree的前序遍歷 def preorder(root):

print (root.dom_elt)

if root.left: # 節點不為空

preorder(root.left)

if root.right:

preorder(root.right)

#對構建好的kd樹進行搜索,尋找與目標點最近的樣本點:

from math import sqrt

from collections import namedtuple

#定義一個namedtuple,分別存放最近坐標點、最近距離和訪問過的節點數

result = namedtuple("Result_tuple", "nearest_point nearest_dist nodes_visited")

def find_nearest(tree, point):

k = len(point) # 數據維度

def travel(kd_node, target, max_dist):

if kd_node is None:

return result([0] * k, float("inf"), 0) # python中用float("inf")和float("-inf")表示正負

nodes_visited = 1

s = kd_node.split # 進行分割的維度

pivot = kd_node.dom_elt # 進行分割的“軸”

if target[s] <= pivot[s]: # 如果目標點第s維小于分割軸的對應值(目標離左子樹更近)

nearer_node = kd_node.left # 下一個訪問節點為左子樹根節點

further_node = kd_node.right # 同時記錄下右子樹

else: # 目標離右子樹更近

nearer_node = kd_node.right # 下一個訪問節點為右子樹根節點

further_node = kd_node.left

temp1 = travel(nearer_node, target, max_dist) # 進行遍歷找到包含目標點的區域

nearest = temp1.nearest_point # 以此葉結點作為“當前最近點”

dist = temp1.nearest_dist # 更新最近距離

nodes_visited += temp1.nodes_visited

if dist < max_dist:

max_dist = dist # 最近點將在以目標點為球心,max_dist為半徑的超球體內

temp_dist = abs(pivot[s] - target[s]) # 第s維上目標點與分割超平面的距離

if max_dist < temp_dist: # 判斷超球體是否與超平面相交

return result(nearest, dist, nodes_visited) # 不相交則可以直接返回,不用繼續判斷

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

# 計算目標點與分割點的歐氏距離

temp_dist = sqrt(sum((p1 - p2) ** 2 for p1, p2 in zip(pivot, target)))

if temp_dist < dist: # 如果“更近”

nearest = pivot # 更新最近點

dist = temp_dist # 更新最近距離

max_dist = dist # 更新超球體半徑

# 檢查另一個子結點對應的區域是否有更近的點

temp2 = travel(further_node, target, max_dist)

nodes_visited += temp2.nodes_visited

if temp2.nearest_dist < dist: # 如果另一個子結點內存在更近距離

nearest = temp2.nearest_point # 更新最近點

dist = temp2.nearest_dist # 更新最近距離

return result(nearest, dist, nodes_visited)

return travel(tree.root, point, float("inf")) # 從根節點開始遞歸

data = [[2,3],[5,4],[9,6],[4,7],[8,1],[7,2]]

kd = KdTree(data)

preorder(kd.root)

[7,2]

[5,4]

[2,3]

[4,7]

[9,6]

[8,1]

from time import clock

from random import random

# 產生一個k維隨機向量,每維分量值在0~1之間

def random_point(k):

return [random() for _ in range(k)]

# 產生n個k維隨機向量

def random_points(k, n):

return [random_point(k) for _ in range(n)]

ret = find_nearest(kd, [3,4.5])

print (ret)

Result_tuple(nearest_point=[2, 3], nearest_dist=1.8027756377319946, nodes_visited=4)

N = 400000

t0 = clock()

kd2 = KdTree(random_points(3, N)) # 構建包含四十萬個3維空間樣本點的kd樹

ret2 = find_nearest(kd2, [0.1,0.5,0.8]) # 四十萬個樣本點中尋找離目標最近的點

t1 = clock()

print ("time: ",t1-t0, "s")

print (ret2)

time: 7.299844505209247 s

Result_tuple(nearest_point=[0.10505669630674175, 0.49542598718931097, 0.8033166919543026], nearest_dist=0.007582362181450973, nodes_visited=53)

五.【實驗小結】

存在一個樣本數據集合(訓練樣本集),并且樣本集中每個數據都存在標簽,即我們知道樣本集中每一數據與所屬分類的對應關系。輸入沒有標簽的新數據后,將新數據每個特征與樣本集中數據對應的特征進行比較,然后算法提取樣本集中特征最相似的數據(最近鄰)的分類標簽。

一般來說我們只選擇樣本數據集中前k個最相似的數據。通常k是不大于20的整數。最后選擇k個最相似數據中出現次數最多的分類,作為新數據的分類。

總結

以上是生活随笔為你收集整理的k近邻算法原理c语言,实验二 K-近邻算法及应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。