计算预测元素与所有训练集样本之间的距离,参考前n个最近距离的样本,预测该样本 # 计算距离,每个样本与所有样本的距离 res = [] for x in X: # 在axis=1列的方向上相加,每个样本得到一个结果 distance = np.sqrt(((self.X - x)**2).sum(axis=1)) idxes = np.argsort(distance)[:self.n_neighbors] res.append(np.round(a=self.y[idxes].mean(),decimals=3)) |
KNN的核心思想是 环境决定个体 比如, 你是一个Java开发,三年工作经验,有个人想知道你的工资, 他不需要问你,只需要知道这一个类多少工资就可以了 又比如,你去相亲,对方说出她的职业,你就知道他的很多信息... 你周围的人不是在搬砖,就是在拉车,一年365天只有过年休息几天,你估计也是如此 你周围的人活的如牛马,勤勤恳恳地劳动,你估计也是 你周围的人都是坐办公室的,你估计也是 你周围的人非富即贵,你估计也是 你周围的人谈笑有鸿儒,往来无白丁,你估计也是 |
环境决定个体,通过分析环境确定个本的性质,这种思想是伟大的 但不是完美的,缺少不维度之间的比较方法 向量内积运算,各个维度上的元素相乘之后,最终相加之后是要化为一个数的 比如,谈对象,有 身高,年龄,相貌,潜力,资产 五项 身高之间的波动一般不超过1米, 资产之间可能有上万的差距, KNN是计算距离,这种情况下,资产波动几十块钱,就淹没了身高的波动,这不合理 这就是出现了两类解决办法 百分比 不同维度之间使用百分比进行比较, 还是归一化的思想,但百分比是更贴切的描述 所有维度的最大值化为1,这种每个元素值的天花板是一样的, 重在一样/差不多,可以是1.2,1.7... 不要出现一个维度波动可以淹没其他维度变化的情况, 让每个维度的波动维持在一个相对统一的量纲上 此时,针对如何归一的细节,普遍有两个方法: 1. 每个元素除以集合中的最大值,批归一化 2. 一个样本中的元素除以这个样本的最大值,层归一化 3. 标准化,减均值,除以标准差,使得元素之间的平均距离化为1,可以针对全体也可以针对某个样本 4. 概率化, 就是将一个样本看作一个概率,不同的特征就是事件,这通常是分类的最后一步, 比如,n分类问题,最终是分为n个类别,不是这一类就是那一类,必定是一种一个类别, 它们地位同等(因为数据比例等比),概率之和为1,也就是某个样本,必是n分类中有的一类 通常的实现方式是softmax,这也是为什么softmax会放在整个算法的最后一步的原因 这些都是归一化的思路,百分比更合适的一些, 但百分比大家想到的是最后之和是1,就是概率了, 但在AI中都是近似计算, 只要能展现出差异即可,所以最终结果不是1也没关系的,可以是90%,也可以是170%,差不多就行 总体来说,就是将所有元素拉到同一个量纲,通常是1附近, 这样,元素之间的比较,就可以跨维度进行对比, 在同一量纲上,差异越大,越好分类 深度学习之间有多个网络,可以理解为刚开始的时候, 有的元素之间相差0.5%, 到最后一层网络的时候,元素之间出现200%的差异,这就好分类 比如,一个水果,51%像苹果,49%像梨, 另外一种情况是,10%像苹果,120%像梨,显示这种情况更好区分一些 注意,这里再次强调了AI是近似,虽然10%+120% !=1,违反了概率的定义, 但也是有用的,表达了后者更像梨的倾向 还有另外一个思路,加权 |
身高,年龄,相貌,潜力,资产,情绪价值 六项进行综合比较,选出一个你满意的 不同维度之间整合,就是各个维度计算之后 相加,没错,就是加法 加法,相加,相融,就代表整合/融合 比如,资产变化会覆盖身高的变化, 那可不可以在资产前面乘一个系数,使资产的变化与身高的变化处于一个量级上? 可以,这就是权加,为每个元素都加一个系数,让所有维度处于一个量级上 接下来的问题是,如何计算这个系数? 人算是不可能了,由计算机算, 可以理解为计算机进行大量的尝试,最终以结果为导向选择了合适的系数 但总体来说,前提让各个维度的量纲处于同一水平上,对后面的计算是有益的 |
AI重全局,不重个体 生的是全局的差异,即一个样本在全体数据集中的位置 是相对位置 是百分比 而KNN,强调的是与自己最近的,最相似的样本,取n个 就是要在全体数据集中找到自己的位置 遍历计算距离,计算距离是过程,目的在于找到离自己最近的样本, 那就是自己在整体中的位置... |
房价:回归问题
from sklearn.datasets import load_boston X,y = load_boston(return_X_y=True) from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.15, random_state=73)
from sklearn.neighbors import KNeighborsRegressor knn = KNeighborsRegressor(n_neighbors=5) knn.fit(X=X_train,y=y_train) y_test_pred1=knn.predict(X=X_test)
y_test_pred1[:7] array([23.56, 24.7 , 40.6 , 15.16, 18.04, 19.7 , 18.02]) mse = ((y_test_pred1 - y_test)**2).mean() mse 21.96151578947368
import numpy as np class MyKNNRegressor(): def __init__(self,n_neighbors=5): """ 自定义KNN算法 """ self.n_neighbors = n_neighbors def fit(self, X, y): """ 本质什么也没有做,但可以做一次排序优化工作 """ self.X = np.array(X) self.y = np.array(y) def predict(self, X): """ 求距离的目的是为了找到距离最近的样本的值 求距离只是一个过程 """ X = np.array(X) if X.ndim !=2: raise Exception("默认是2维结构,批量预测") # 计算距离,每个样本与所有样本的距离 res = [] for x in X: # 在axis=1列的方向上相加,每个样本得到一个结果 distance = np.sqrt(((self.X - x)**2).sum(axis=1)) idxes = np.argsort(distance)[:self.n_neighbors] res.append(np.round(a=self.y[idxes].mean(),decimals=3)) return np.array(res) knn_my = MyKNNRegressor() knn_my.fit(X=X_train,y=y_train) y_test_pred2 = knn_my.predict(X=X_test) mse = ((y_test_pred2 - y_test)**2).mean() mse 21.96151578947368 y_test_pred2[:7] array([23.56, 24.7 , 40.6 , 15.16, 18.04, 19.7 , 18.02]) |
def fit(self, X, y): """ 本质什么也没有做,但可以做一次排序优化工作 """ self.X = np.array(X) self.y = np.array(y) KNN的训练代码没有处理逻辑,直接在处理逻辑在预测中 将预测时,即时计算 如果数据量大,比较慢 ----------------------------------------------------------- |
def fit(self, X, y): 这里的X,y就是超参数,参数就参数了,为什么带个超? 这是因为在“参数”一词在AI中特指算法内部的参数, 而X,y是外部输入的,就再起一个名字,叫超参数 当你告诉不懂AI的人,说你要进行超参数优化, 听起来是不是比参数优化高级那么一点点... ---------------------------------------------------------------- |
import numpy as np class KNNCorr(): def __init__(self,n_neighbors=1): """相似推荐,从指定数据集寻找最自己最接受的数据 """ self.n_neighbors = n_neighbors def fit(self, X=None): """目标数据,训练数据 - 以训练 """ self.X = X # 在fit方法中预存转置矩阵 # self.X_T = self.X.T.copy(order='C') # C连续内存布局 def predict(self, X): """预测 - 预测目标数据中与自己相似度最高的数据的索引 """ X = np.array(X) if X.ndim !=2: raise Exception("默认是2维结构,批量预测") # 计算距离,每个样本与所有样本的距离 res = [] # 将for循环替换为矢量化计算 # 在数据的第2维,即Index=1的位置上增加一维,index=0上代表批次维度,增加一维后,表示每个元素是(1,3)的矩阵, # 减X时,会先进行广播,[b,1,n] -- [b,m,n] m为X的元素个数,即self.X中的每个元素会先自复制到与X同元素个数 distance_matrix = np.sqrt(((X[:, np.newaxis] - self.X)**2).sum(axis=2)) index = distance_matrix.argmin(axis=1) return index import numpy as np np.random.seed(42) X = np.random.rand(7,3) X_test =X[:3] y_index = model.predict(X_test) X[y_index] array([[0.37454012, 0.95071431, 0.73199394], [0.59865848, 0.15601864, 0.15599452], [0.05808361, 0.86617615, 0.60111501]]) X_test array([[0.37454012, 0.95071431, 0.73199394], [0.59865848, 0.15601864, 0.15599452], [0.05808361, 0.86617615, 0.60111501]]) |
|
from tpf import load_boston X_train, y_train, X_test, y_test = load_boston(split=True,test_size=0.15) import numpy as np class MyKNNRegressor2(): """改变距离的度量方法 - 没有开平方 """ def __init__(self,n_neighbors=5): """ 自定义KNN算法 """ self.n_neighbors = n_neighbors def fit(self, X, y): """ 本质什么也没有做,但可以做一次排序优化工作 """ self.X = np.array(X) self.y = np.array(y) def predict(self, X): """ 求距离的目的是为了找到距离最近的样本的值 求距离只是一个过程 """ X = np.array(X) if X.ndim !=2: raise Exception("默认是2维结构,批量预测") # 计算距离,每个样本与所有样本的距离 res = [] for x in X: # 在axis=1列的方向上相加,每个样本得到一个结果 distance = ((self.X - x)**2).sum(axis=1) idxes = np.argsort(distance)[:self.n_neighbors] res.append(np.round(a=self.y[idxes].mean(),decimals=3)) return np.array(res) knn_my = MyKNNRegressor2() knn_my.fit(X=X_train,y=y_train) y_test_pred2 = knn_my.predict(X=X_test) mse = ((y_test_pred2 - y_test)**2).mean() mse 21.96151578947368 |
class MyKNNRegressor3(): """改变距离的度量方法 - 没有开平方 """ def __init__(self,n_neighbors=5): """ 自定义KNN算法 """ self.n_neighbors = n_neighbors def fit(self, X, y): """ 本质什么也没有做,但可以做一次排序优化工作 """ self.X = np.array(X) self.y = np.array(y) def predict(self, X): """ 求距离的目的是为了找到距离最近的样本的值 求距离只是一个过程 """ X = np.array(X) if X.ndim !=2: raise Exception("默认是2维结构,批量预测") # 计算距离,每个样本与所有样本的距离 res = [] for x in X: # 在axis=1列的方向上相加,每个样本得到一个结果 distance = (np.abs((self.X - x))).sum(axis=1) idxes = np.argsort(distance)[:self.n_neighbors] res.append(np.round(a=self.y[idxes].mean(),decimals=3)) return np.array(res) knn_my = MyKNNRegressor3() knn_my.fit(X=X_train,y=y_train) y_test_pred2 = knn_my.predict(X=X_test) mse = ((y_test_pred2 - y_test)**2).mean() mse 18.638584210526318 平方与不平方没有任何的区别 而L1距离与L2距离有所区别,从KNN的效果来看,L1距离比L2距离的MSE更小一些 |
距离的计算不是目的,是一个过程, 计算距离是为了找出离目标最近的n个样本 找最近的n个样本才是目的 如此,达到同样的目的,就可以有多种方案选择 一段代码要注意分析该代码的目的是什么? 哪些只是计算的一种方式,只是一个过程 要区分过程和目的... ----------------------------------------------------------------------- |
|
|
sklearn2pmml github PMML讲解及使用