原理:
K近邻
选取欧式距离最近的k个特征点
分类:作为投票,
回归:取均值
KNN算法–优缺点:
优点:
1.思想简单,容易实现,可分类、回归
2.依赖局部近邻,当样本有类域交叉,依然适用
3.对异常数据不敏感,准确率高
缺点:
1.惰性计算,预测时间复杂度高,速度慢
2.存储整个数据集,空间复杂度高
3.样本不均衡,对稀有类别准确率不够高
优化方面
1.特征很多,考虑降维,降低计算复杂度
2.训练时,采用KD树或者对样本预处理,降低搜索近邻时的复杂度
knn分类
import numpy as np
# 鸢尾花数据集
from sklearn.datasets import load_iris
# 数据集切分
from sklearn.model_selection import train_test_split
class KNeighborsClassifier(object):
"""
自定义分类器
"""
def __init__(self, n_neighbors=5):
"""
设置超参数
"""
self.n_neighbors = n_neighbors
def fit(self, X, y):
"""
模型训练 啥也没干
"""
self.X = np.array(X)
self.y = np.array(y)
def predict(self, X):
"""
模型预测
1.找k个最近的邻居
2.统计K个邻居的类别情况
3.计算出现最多的类别
"""
X = np.array(X)
# 如果不是2维 自定义报错
if X.ndim != 2:
raise Exception("非二维")
# 结果列表
result = []
for x in X:
# 一个测试数据 距离 每一个训练集数据的距离 是多少
# 欧氏距离
dist = np.sqrt(((self.X - x) ** 2).sum(axis=1))
# 索引排序 截取排在前面的k个邻居 默认小-大
args = np.argsort(dist)[:self.n_neighbors]
# 取出对应的标签 np可以根据索引取出多个
labels = self.y[args]
# .tolist() 数组或者矩阵等,转为列表形式
# .count 统计出现次数
# 函数式编程:语法 max(x1, key=处理) key代表x1内的每一个值
# set()去重 找到类别1、类别2、 计算每个类别出现的次数 选次数最高的 类别
result.append(max(set(labels), key=labels.tolist().count))
return np.array(result)
# 加载数据集
X, y = load_iris(return_X_y=True)
# 训练集数据、测试集数据、训练集标签、测试集标签、 数据集分割为 80%训练 20%测试
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.2)
# # print(X_train)
# 构建模型
knn = KNeighborsClassifier(n_neighbors=5)
# 模型训练
knn.fit(X=X_train, y=y_train)
# 模型预测
y_pred = knn.predict(X=X_test)
print(y_pred)
print(y_test)
print(y_pred == y_test)
# 准确率 np格式 使用.mean()求均值 列表不可以
acc = (y_pred == y_test).mean()
print(acc)
knn回归
import numpy as np
# # 波士顿房价预测数据
# from sklearn.datasets import load_boston
# 利福尼亚住房数据集
from sklearn.datasets import fetch_california_housing
# 数据集切分
from sklearn.model_selection import train_test_split
class KNeighborsRegressor(object):
"""
自定义归回器
"""
def __init__(self, n_neighbors=5):
"""
设置超参数
"""
self.n_neighbors = n_neighbors
def fit(self, X, y):
"""
模型训练 啥也没干
"""
self.X = np.array(X)
self.y = np.array(y)
def predict(self, X):
"""
模型预测
1.找k个最近的邻居
2.统计K个邻居的均值
"""
X = np.array(X)
# 如果不是2维 自定义报错
if X.ndim != 2:
raise Exception("非二维")
# 结果列表
result = []
for x in X:
# 一个测试数据 距离 每一个训练集数据的距离 是多少
# 欧氏距离
dist = np.sqrt(((self.X - x) ** 2).sum(axis=1))
# 索引排序 截取排在前面的k个邻居 默认小-大
args = np.argsort(dist)[:self.n_neighbors]
# 取出对应的标签 np可以根据索引取出多个
labels = self.y[args]
# 求均值
result.append(labels.mean())
return np.array(result)
# 加载数据集
X, y = fetch_california_housing(return_X_y=True)
# 训练集数据、测试集数据、训练集标签、测试集标签、 数据集分割为 80%训练 20%测试
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.2)
# # print(X_train)
# 构建模型
knn = KNeighborsRegressor(n_neighbors=5)
# 模型训练
knn.fit(X=X_train, y=y_train)
# 模型预测
y_pred = knn.predict(X=X_test)
print(y_pred)
print(y_test)
# 准确率 np格式 使用.mean()求均值 列表不可以
mse = ((y_pred - y_test) ** 2).mean()
print(mse)