目录
一:K邻近算法介绍:
- 1:首先要有原始已知标签的数据。
- 2:把需要预测的点和所有已知的点计算距离。
- 3:找到和待遇测点最近的K个点。
- 4:根据K个点的标签确定待测点的标签。
- KNN算法可以做回归问题,也可以做分类问题。
- knn算法没有得到模型,它是机器学习中唯一一个不需要训练过程的算法。
1:欧拉距离:
2:使用K邻近算法实现分类:
1:准备特征值和标签值:
import numpy as np
import matplotlib.pyplot as plt
# 1:定义特征值位置
raw_data_x=[[3.3144558 , 2.33542461],
[3.75497175, 1.93856648],
[1.38327539, 3.38724496],
[3.09203999, 4.47090056],
[2.58593831, 2.13055653],
[7.41206251, 4.80305318],
[5.912852 , 3.72918089],
[9.21547627, 2.8132231 ],
[7.36039738, 3.35043406],
[7.13698009, 0.40130301]]
# 2:定义特征值的属性(0,1是上面标签的类别)
raw_data_y=[0,0,0,0,0,1,1,1,1,1]
# 3:转换成numpy的多维数组
X_train = np.array(raw_data_x)
y_train = np.array(raw_data_y)
2:验证多维数组的方法:
3:利用matplotlib绘制图像:
#利用matplotlib绘制图像
plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],color='g')
plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],color='r')
plt.show()
4:加入预测点,再次绘制图像:
# 创建预测点数组
x=np.array([8.093607318,3.365731514])
plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],color='g')
plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],color='r')
# 将预测点加入图中
plt.scatter(x[0],x[1],color='b')
plt.show()
5:实现距离计算:
from math import sqrt # 开根号的函数
# 1: 现在X_train二维数组中,取出每个的一维数组
# 一维数组和一维数组之间可以直接相减 x_train - x 即:[3.3144558 , 2.33542461] - [8.093607318,3.365731514]
# **2 指的是将差值的一维数组,每个数都平方操作。
# np.sum(平方后的一维数组)就是一维数组求和
# sqrt(数):就是求出的最后的开平方后的和
# 最后拿到的数据是个数组,就是各个点到预测点的距离。
distances = [sqrt(np.sum((x_train-x)**2)) for x_train in X_train]
print(distances)
# 对计算的距离进行排序:根据数值进行排序,返回的是排序后的下标
nearest = np.argsort(distances)
# 打印下标
print(nearest)
6:定义k值,得出计算结果:
k=6
# 获取距离最近的前k个数据的下标,拿到的是最近的6个数的便签值。
topK_y = [y_train[i] for i in nearest[:k]]
#统计每个y值出现的次数
from collections import Counter
# 拿到的是值与数量的字典
votes = Counter(topK_y)
print(votes) # Counter({1: 5, 0: 1})
#获取出现次数最多的那个y的取值
print(votes.most_common(1)) # [(1, 5)],返回一个数组,先按频数排序,如果频率相同,则按照字母排序。
predict_y = votes.most_common(1)[0][0] # 取出数组的第一个元祖的,元祖第一个位置(key)
print(predict_y)# 这个就应该是该元素的便签值
3: sklearn中knn算法的应用:
1:安装sklearn :
2:使用sklearn进行预测:
# 1: 导包
from sklearn.neighbors import KNeighborsClassifier
#2:创建knn算法的分类器实例,选取最近的6个点
knn_classifier = KNeighborsClassifier(n_neighbors=6)
#拟合训练数据
knn_classifier.fit(X_train,y_train)
#将样本维度变为二维,因为我训练的维度就是二维的。
x1 = x.reshape(1, -1)
#利用knn算法进行预测
y_predict = knn_classifier.predict(x1)
#得出预测结果
y_predict[0]
# 输出 1
4:自己写代码模拟KNN算法(了解):
1:自己定义一个KNN算法:
import numpy as np
from math import sqrt
from collections import Counter
class KNNClassifier:
def __init__(self, k):
"""初始化kNN分类器"""
assert k >= 1, "k must be valid"
self.k = k
self._X_train = None
self._y_train = None
def fit(self, X_train, y_train):
"""根据训练数据集X_train和y_train训练kNN分类器"""
assert X_train.shape[0] == y_train.shape[0], \
"the size of X_train must be equal to the size of y_train"
assert self.k <= X_train.shape[0], \
"the size of X_train must be at least k."
self._X_train = X_train
self._y_train = y_train
return self
def predict(self, X_predict):
"""给定待预测数据集X_predict,返回表示X_predict的结果向量"""
assert self._X_train is not None and self._y_train is not None, \
"must fit before predict!"
assert X_predict.shape[1] == self._X_train.shape[1], \
"the feature number of X_predict must be equal to X_train"
y_predict = [self._predict(x) for x in X_predict]
return np.array(y_predict)
def _predict(self, x):
"""给定单个待预测数据x,返回x的预测结果值"""
assert x.shape[0] == self._X_train.shape[1], \
"the feature number of x must be equal to X_train"
distances = [sqrt(np.sum((x_train - x) ** 2))
for x_train in self._X_train]
nearest = np.argsort(distances)
topK_y = [self._y_train[i] for i in nearest[:self.k]]
votes = Counter(topK_y)
return votes.most_common(1)[0][0]
def __repr__(self):
return "KNN(k=%d)" % self.k
2:将kNN.py文件放入到和jupyter的代码相同的目录下,在jupyter中利用魔法方法进行代码运行。
#利用魔法方法加载kNN.py文件
%run knn/kNN.py
#创建实例
knn_clf = KNNClassifier(k=6)
#拟合训练集
knn_clf.fit(X_train,y_train)
#预测输入样例
y_predict = knn_clf.predict(x1)
#得出预测结果
y_predict[0]
二:划分数据集:
- 一般要将数据集划分成测试集和训练集。
- 训练集参与模型训练,测试集不参与模型训练,只用作评估。一般2/8分。
1:自己模拟实现:
1: 加载数据:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
2: 获取特征值和目标值:
#获取sklearn中的内置数据集
iris = datasets.load_iris()
print(iris.data) # 获取特征值(多维数组)
print(iris.target)# 获取标签值(目标值,一维数组)
3:划分测试集和训练集:
思路:1:先求测试集/训练集的长度,根据长度生成随机的一个列表。
2:根据随机比例,和训练集长度,将列表划分成两部分,一部分存储的是训练集的下标,另一部分存储的是测试集的下标。
3:然后根据这个列表,划分测试集和训练集。
X = iris.data
y = iris.target
# 1:将长度X对应的索引值进行随机排列,返回的是打乱顺序的列表。
shuffle_indexes = np.random.permutation(len(X))
#2: 定义测试机的比例
test_ratio = 0.2
#3: 得到测试集对应的数据量
test_size = int(len(X) * test_ratio)
#4:获取测试集的索引和训练集的索引
test_indexes = shuffle_indexes[:test_size] # 测试集的索引
train_indexes = shuffle_indexes[test_size:]# 训练集的索引
#获取训练数据集
X_train = X[train_indexes]
y_train = y[train_indexes]
#获取测试数据集
X_test = X[test_indexes]
y_test = y[test_indexes]
2:封装成工具类:
1:C:\Users\11737\knn,在knn文件夹中创建model_selection.py文件,文件中存入这些内容:
import numpy as np
def train_test_split(X, y, test_ratio=0.2, seed=None):
"""将数据 X 和 y 按照test_ratio分割成X_train, X_test, y_train, y_test"""
assert X.shape[0] == y.shape[0], \
"the size of X must be equal to the size of y"
assert 0.0 <= test_ratio <= 1.0, \
"test_ration must be valid"
if seed:
np.random.seed(seed)
shuffled_indexes = np.random.permutation(len(X))
test_size = int(len(X) * test_ratio)
test_indexes = shuffled_indexes[:test_size]
train_indexes = shuffled_indexes[test_size:]
X_train = X[train_indexes]
y_train = y[train_indexes]
X_test = X[test_indexes]
y_test = y[test_indexes]
return X_train, X_test, y_train, y_test
2: C:\Users\11737\knn中新建_init_.py文件,使其变为工程目录,以便于后面能够直接导入train_test_split方法。
3:测试封装后的代码:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
#获取sklearn中的内置数据集
iris = datasets.load_iris()
X = iris.data # 特征值
y = iris.target # 目标值
from knn.model_selection import train_test_split # 导入自己封装的函数
X_train,X_test,y_train,y_test = train_test_split(X,y)# 分好数据集和测试集
from knn.kNN import KNNClassifier # 导入训练模型
knn_clf = KNNClassifier(k=6) # 创建对象
knn_clf.fit(X_train,y_train) # 训练
y_predict = knn_clf.predict(X_test) # 测试集进行预测
3:使用sklearn中的train_test_split:
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
三:划分精确度:
1:自己实现:
1: 加载数据:
2:拿出一个数据测试:
3:使用KNN算法进行预测:
from knn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_ratio=0.2) # 使用我们自己的对测试集进行划分
from knn.kNN import KNNClassifier
knn_clf = KNNClassifier(k=6) # 构造模型
knn_clf.fit(X_train,y_train) # 进行训练
y_predict = knn_clf.predict(X_test) # 进行预测
sum(y_predict == y_test)/y_test.shape[0] # 计算准确率
2:封装成工具类使用:
1:计算精确度的代码进行封装:
新建一个文件专门用来计算精确度:C:\Users\11737\knn
2:kNN.py创建一个方法,直接能调用这个方法,得到准确率:
def score(self, X_test, y_test):
"""根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""
y_predict = self.predict(X_test)
return accuracy_score(y_test, y_predict)
3: 进行测试:
knn_clf.score(X_test,y_test)
3:直接调用sklearn中的accuracy_score进行划分:
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
#划分数据集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
#训练knn模型
knn_classifier = KNeighborsClassifier(n_neighbors=6)
knn_classifier.fit(X_train,y_train)
#预测测试集
y_predict = knn_classifier.predict(X_test)
#计算准确率
from sklearn.metrics import accuracy_score
# 使用accuracy_score
accuracy_score(y_test,y_predict)
四:超参数:
1:超参数概念:
2:代码实现寻找最优K值:
1: 先用一个随机的K测试:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from sklearn import datasets
digits = datasets.load_digits()
X = digits.data
y = digits.target
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
knn_classifier = KNeighborsClassifier(n_neighbors=6)
knn_classifier.fit(X_train,y_train)
#得到评分数据
knn_classifier.score(X_test,y_test)
得到的准确率是:0.9888888888888889
2:寻找最优K:
best_score = 0.0
best_k = -1
for k in range(1,11):
knn_classifier = KNeighborsClassifier(n_neighbors=k)
knn_classifier.fit(X_train,y_train)
score = knn_classifier.score(X_test,y_test)
print("k={}, score={}".format(k, score))
if score > best_score:
best_k = k
best_score = score
print("best_k =",best_k)
print("best_score =",best_score)
3:K近邻算法的优化:
1: 存在的问题:
2:在sklearn的官方问题中存在此问题的具体实现,参数weights默认为uniform,不考虑距离,如传入distance,则考虑距离。
best_score = 0.0
best_k = -1
for method in ["uniform","distance"]:
for k in range(1,11):
knn_classifier = KNeighborsClassifier(n_neighbors=k,weights=method)
knn_classifier.fit(X_train,y_train)
score = knn_classifier.score(X_test,y_test)
if score > best_score:
best_k = k
best_score = score
best_method = method
print("best_method =",best_method)
print("best_k =",best_k)
print("best_score =",best_score)
注意第二次的时候,只考虑距离,跟数值就没关系了,即使个数很多,我们也要选择距离近的那个。
五:归一化:
1:为什么要归一化:
问题:我们有两个样本,每个样本有两个特征,一个是肿瘤大小,一个是肿瘤的发现时间。
2:归一化的方式?
1:最值归一化:
2:均值方差归一化:
3:代码实现归一化:
1: 一维数组最值归一化:
2:二维数组归一化:
3:均值方差归一化:
#随机生成shape为(50,2)数值范围在0-100范围内的二维数组
X2 = np.random.randint(0,100,(50,2))
#转换为float类型
X2 = np.array(X2,dtype=float)
#对两个样本进行均值方差归一化
X2[:,0] = (X2[:,0]-np.mean(X2[:,0]))/np.std(X2[:,0])
X2[:,1] = (X2[:,1]-np.mean(X2[:,1]))/np.std(X2[:,1])
4:sklearn中的归一化:
1: 数据的准备:
import numpy as np
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 划分训练集和测试集
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,test_size=0.2,random_state=1)
2:进行归一化处理:
# 进行均值方差归一化处理
from sklearn.preprocessing import StandardScaler
# 1:创建对象
ss = StandardScaler()
# 2:学习均值和方差
ss.fit(X_train,y_train)
print(ss.mean_)# 内部的均值
print(ss.scale_) # 内部的方差
#3:转换训练集和测试集
X_train1 = ss.transform(X_train)
X_test1 = ss.transform(X_test)
3: 对归一化和没有归一化的进行测试: