仅供自己复习回顾使用,若有侵权可删除
KNN 分类器一般被认为是一种懒惰( lazy)的学习器,因为严格来说它并没有训练一个模型用来做预测,而是将观察值的分类判定为离它最近的 k 个观察值中所占比例最大的那个分类。
!!!在寻找最近的邻居或者使用基于距离的某种学习算法时,很重要的一件事是转换特征,使所有特征采用同样的单位。
from sklearn import datasets
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import StandardScaler
iris = datasets.load_iris()
features = iris.data
# 创建 standardizer
standardizer = StandardScaler()
# 特征标准化
features_standardized = standardizer.fit_transform(features)
# 两个最近的观察值
nearest_neighbors = NearestNeighbors(n_neighbors=2).fit(features_standardized)
# 创建一个观察值
new_observation = [ 1, 1, 1, 1]
# 获取离观察值最近的两个观察值的索引,以及到这两个点的距离
distances, indices = nearest_neighbors.kneighbors([new_observation])
'''
NearestNeighbors默认使用闵可夫斯基距离, p=1,其实就是曼哈顿距离;如果p=2就是欧氏距离
metric='euclidean'
'''
# 查看最近的两个观察值
features_standardized[indices]
# 每个观察值和它最近的 3 个邻居的列表(包括它自己)
nearest_neighbors_with_self = nearestneighbors_euclidean.kneighbors_graph(
features_standardized).toarray()
# 从最近邻居的列表里移除自己
for i, x in enumerate(nearest_neighbors_with_self):
x[i] = 0
创建一个 KNN 分类器
# 加载库
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
# 创建 standardizer
standardizer = StandardScaler()
# 标准化特征
X_std = standardizer.fit_transform(X)
knn = KNeighborsClassifier(n_neighbors=5, n_jobs=-1).fit(X_std, y)
# 创建两个观察值
new_observations = [[ 0.75, 0.75, 0.75, 0.75],[ 1, 1, 1, 1]]
# 预测这两个观察值的分类
knn.predict(new_observations)
# 查看每个观察值分别属于 3 个分类中的某一个的概率
knn.predict_proba(new_observations)
确定最佳的邻域点集的大小
使用GridSearchCV这样的模型选择技术 :如果 k=n(这里n是观察值的数量),那么偏差就会很大而方差很小。如果 k=1,那么偏差会很小,但是方差很大。只有找到了能在偏差和方差之间取得折中的k值,才能得到最佳的KNN分类器。
# 加载库
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import GridSearchCV
# 加载数据
iris = datasets.load_iris()
features = iris.data
target = iris.target
standardizer = StandardScaler()
features_standardized = standardizer.fit_transform(features)
knn = KNeighborsClassifier(n_neighbors=5, n_jobs=-1)
# 创建一个流水线
pipe = Pipeline([("standardizer", standardizer), ("knn", knn)])
# 确定一个可选值的范围
search_space = [{"knn__n_neighbors": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}]
# 创建 grid 搜索
classifier = GridSearchCV(
pipe, search_space, cv=5, verbose=0).fit(features_standardized, target)
# 最佳邻域的大小 (k)
classifier.best_estimator_.get_params()["knn__n_neighbors"]
创建一个基于半径的最近邻分类器
在不太常用的基于半径的最近邻分类器中,观察值的分类是根据某一半径 r 范围内所有观察值的分类来预测的
from sklearn.neighbors import RadiusNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn import datasets
iris = datasets.load_iris()
features = iris.data
target = iris.target
# 创建 standardizer
standardizer = StandardScaler()
# 标准化特征
features_standardized = standardizer.fit_transform(features)
# 训练一个基于半径的最近邻分类器
rnn = RadiusNeighborsClassifier(radius=.5, n_jobs=-1).fit(features_standardized, target)
'''
radius 半径
outlier_label,用来指定如果一个观察值周围没有其他观察值在半径radius的范围内,这个观察值应该被标记为什么,是有用的分辨界外点的方法。
'''
# 创建两个观察值
new_observations = [[ 1, 1, 1, 1]]
# 预测这两个观察值的分类
rnn.predict(new_observations)