机器学习入门-3(KNN)

 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)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值