k近邻:两个样本足够相似的话就有更高的概率属于同一个类别,看和它最相似的k个样本中那个类别最多
对KNN来说训练集就是模型


寻找超参数:领域知识、经验数值、实验搜索
- 距离
p=1,2,3…
KNN中距离的应用

由此引入距离权重,权重为距离的倒数,这也是一种超参数weights=‘uniform’ ‘distance’
超参数之间可能存在相互依赖的关系,比如weights中的‘distance’和p,所以简单使用for循环的方式进行网格搜索是不好的
更多的距离定义:向量空间余弦相似度、调整余弦相似度、皮尔森相关系数、Jaccard相似系数
- 数据归一化
数据的归一化:由于各个特征的量纲不同,计算样本间距离容易被数值较大的所主导,这样计算得到的距离是有偏差的,不能非常好地同时反映样本中每个特征的重要程度,所以要进行数据的处理,归一化,将每个特征的数据都映射到同一个尺度中
最值归一化normalization; 均值方差归一化standardization

分数、像素等都是有边界的,而收入等没有边界,或者说差距过大,这时候数据就会有偏



- KNN回归
平均或加权平均
- KNN的一些思考

缺点2:高度数据相关,如果k=3,预测样本周围有两个错误样本,预测结果就很可能错误,哪怕是其他点都正确
#手动封装KNN,但是sklearn里面的不是这样简单的
from collections import Counter
class KNN_classifier:
def __init__(self,k):#构造函数
self.k=k
self._X_train=None#私有的成员变量
self._y_train=None
def fit(self,X_train,y_train):
self._X_train=X_train
self._y_train=y_train
return self
def predict(self,X_test):
y_pre=[self._ypre(i) for i in X_test]
return np.array(y_pre)
def _ypre(self,x):
distance=np.sqrt(np.sum((self._X_train-x)**2,axis=1))
near=np.argsort(distance)
top_k=[self._y_train[i] for i in near[:self.k]]
votes=Counter(top_k)#Counter(数组)返回字典,key是数组元素,值是对应元素的个数
return votes.most_common(1)[0][0]#votes.most_common(n)n表示最多的几个,返回票数最多的n个元素的[(key,value).....]
def score(self,X_test,y_test):
y_pre=self.predict(X_test)
return np.sum(y_test==y_pre)/len(y_test)
def __repr__(self):
return "KNN K="+str(self.k)
sklearn库里面的knn
from sklearn.neighbors import KNeighborsClassifier
knn=KNeighborsClassifier(n_neighbors=6)
knn.fit(X_train,y_train)
y_pre=knn.predict(x)#希望传入的是矩阵形式
手动封装train_test_split
def train_test_split1(X,y,test_ratio=0.2,seed=None):
if seed:
np.random.seed(seed)
shuffle_index=np.random.permutation(len(y))
#shuffle_index=np.random.permutation(len(X))#对0-len-1乱序返回
test_size=int(test_ratio*len(y))
X_test=X[:test_size]
X_train=X[test_size:]
y_train=y[test_size:]
y_test=y[:test_size]
return X_train,X_test,y_train,y_test
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)
np.sum(y_test==y_pre)/len(y_test)
sklearn中:
from sklearn.metrics import accuracy_score
accuracy_score(y_test,y_pre)
加载鸢尾花数据集
from sklearn import datasets
iris=datasets.load_iris()
X=iris.data
y=iris.target
交叉验证
from sklearn.metrics import accuracy_score
accuracy_score(y_test,y_pre)
grid search数组类型,每个元素是一个字典,每个字典表示一组网格搜索,key就是超参名,value就是对应的值
para_grid=[
{
'weights':['uniform'],
'n_neighbors':[i for i in range(1,11)]
},
{
'weights':['distance'],
'n_neighbors':[i for i in range(1,11)],
'p':[i for i in range(1,6)]
}
]
from sklearn.model_selection import GridSearchCV#CV交叉验证
from sklearn.neighbors import KNeighborsClassifier
knn=KNeighborsClassifier()
grid_search=GridSearchCV(knn,para_grid,n_jobs=2,verbose=2)
n_jobs计算机核的数量,n_jobs=-1所有的核都用上
verbose搜索过程输出信息,值越大,输出信息越多
grid_search.fit(X_train,y_train)
grid_search.best_estimator_#返回最佳分类器
grid_search.best_params_#返回最佳分类器对应的参数
grid_search.best_score_
像这种不是用户传入的参数,程序自己计算出来的参数最后有一个下划线
knn=grid_search.best_estimator_
standardscaler
from sklearn.preprocessing import StandardScaler
ss=StandardScaler()
ss.fit(X)#直接按照每一列也就是每个维度每个特
ss.mean_#均值
ss.scale_#方差
X_train1=ss.transform(X_train)
X_test1=ss.transform(X_test)
class StandardScaler1:
def __init__(self):
self.mean_=None
self.scaler_=None
def fit(self,X):
self.mean_=np.array([np.mean(X[:,i]) for i in range(np.shape(X)[1])])
self.scaler_=np.array([np.std(X[:,i]) for i in range(np.shape(X)[1])])
return self
def transform(self,X):
return (X-self.mean_)/self.scaler_
ss1=StandardScaler1()
ss1.fit(X_train)
ss1.mean_
X_train2=ss1.transform(X_train)
X_test2=ss1.transform(X_test)
2861

被折叠的 条评论
为什么被折叠?



