KNN与线性分类器

问题:

图像分类:我们给出了一组标记图像的训练集,要求预测测试集上的标签。

KNN(K最近邻算法 K-NearestNeighbor):

所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。

如何判断两张图片的不同:

  1. 曼哈顿算法(L1)
    在这里插入图片描述

每张图片由大量的像素点组成(0-255),两者像素点相减并求和,如果相同则应该为0

  1. 欧式距离算法(L2)
    在这里插入图片描述

使用平方开根号的方法定义距离

困难:

  1. 使用哪种距离算法
  2. 如何确定超参数K,参数取什么工作的最好(交叉验证等)

overfit问题:
在这里插入图片描述
某一种类别的数据过大时可能会存在误判的情况。当过于的追求准确度而增大K值,则可能会出现overfit问题

KNN在图片处理上已经不用

当图片出现偏移,灰度不同问题时,使用L2都会使判断出现误差,这是不可避免的

线性分类器:

线性分类器

构造一个函数,输入一张图片,对每一类输出一个数值在这里插入图片描述

例子:

假设pixel是单列的,有三个类别,有如下结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
损失函数

分类器(W)不一定按照我们的想法工作的很好,损失函数的作用就是量化分类器(W)的好坏


实现:

环境

  1. python
  2. numpy
  3. scikit-learn

scikit-learn是面向机器学习的Python开源框架,scikit-learn可以在一定范围内为开发者提供非常好的帮助。它内部实现了各种各样成熟的算法,容易安装和使用,样例丰富,而且教程和文档也非常详细。

在scikit-learn的datasets数据集种有多种多样的数据库帮助学习,本例使用iris集(某种花),它有4种属性,3个类别

	from sklearn import  datasets
	# 一种花的数据集
	iris=datasets.load_iris()
	# 花的属性
	iris_x=iris.data
	# 花的类别
	iris_y=iris.target
	print(iris_x)
	print(iris_y)

在这里插入图片描述
上图截取一部分打印,分割线以上为数据属性集(data),下面为标签集,可以看到有4个属性,3个类别,每一行对应一类

创建KNN

#用于分割数据集
from  sklearn.model_selection import train_test_split
# KNN对象
from  sklearn.neighbors import  KNeighborsClassifier
# 将数据分为测试部分和训练部分,训练部分占比30%
# 同时将数据打乱,增加数据的随机性
X_train,X_test,y_train,y_test=train_test_split(iris_x,iris_y,test_size=0.3)
# 实例化一个KNN
knn=KNeighborsClassifier()
# 传入data、label 进行训练train
knn.fit(X_train,y_train)
# 将测试数据传入已经训练好的model种,获取label
print(knn.predict(X_test))
print('----------')
# 对比y_test 查看效果
print(y_test)

在这里插入图片描述
可以看到训练train效果很好,几乎100%,只判断错了,但是也从另一方面说明再好的机器学习也会有误差

创建线性分类器

	from sklearn import  datasets
	import matplotlib.pyplot as plt
	from  sklearn.linear_model import LinearRegression
	lr=LinearRegression()#y=wx+b
	#随机生成数据
	#也可以同上加载显现有数据
	X,y=datasets.make_regression(n_samples=100,n_features=100,n_targets=30,noise=1000)
	lr.fit(X,y)
	print("获取W:",lr.coef_)
	print("获取b:",lr.intercept_)
	print("获取分数(吻合程度):",lr.score(X,y))

scikit-learn补充:

当数据项相差过大时,机器训练的过程是相当曲折的,如下图曲线1,这样可能会造成较大的误差,但是先对数据进行预处理,在进行训练会减小机器学习的困难,如图2
在这里插入图片描述

	# 预处理
	from  sklearn import preprocessing
	from  sklearn.datasets import make_classification
	from  sklearn.model_selection import train_test_split
	from  sklearn.svm import  SVC
	import matplotlib.pyplot as plt
	
	X,y=make_classification(n_samples=300,n_features=2,random_state=22,n_redundant=0,n_informative=2,n_clusters_per_class=1,scale=100)
	plt.scatter(X[:,0],X[:,1])
	plt.show()
	# X=preprocessing.scale(X)
	X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3)
	clf=SVC()
	clf.fit(X_train,y_train)
	print(clf.score(X_test,y_test))

结果:0.5111111111111111
添加preprocessing.scale(X)后,结果:0.9222222222222223


交叉验证(cross validation)

validation_curve模块测试train和cross_validation

前提:

	from  sklearn.datasets import load_iris
	from  sklearn.model_selection import train_test_split
	from  sklearn.neighbors import  KNeighborsClassifier
	iris=load_iris()
	data=iris.data
	label=iris.target
	X_train,X_test,y_train,y_test=train_test_split(data,label,test_size=0.3)
	for i  in range(1,100):
		#n_neighbors即为k
	    knn=KNeighborsClassifier(n_neighbors=i)
	    knn.fit(X_train,y_train)
	    print(i,knn.score(X_test,y_test))

1 0.9555555555555556
2 0.9555555555555556
3 0.9555555555555556
4 0.9555555555555556
5 0.9555555555555556
6 0.9777777777777777
7 0.9555555555555556
8 1.0
9 0.9777777777777777
10 0.9777777777777777
11 0.9777777777777777

可以看到当k等于8时是比较准确的预测的,但是这是非常不好的其实,因为我们的测试集是有限的非常少的
在这里插入图片描述

这个时候就要用到交叉验证了(cross validation)
在这里插入图片描述
将训练集(train data)循环折叠,分成5组,然后取平均

	from  sklearn.datasets import load_iris
	from  sklearn.model_selection import train_test_split
	from  sklearn.neighbors import  KNeighborsClassifier
	# 可以获取交叉验证得分
	from  sklearn.model_selection import cross_val_score
	iris=load_iris()
	data=iris.data
	label=iris.target
	X_train,X_test,y_train,y_test=train_test_split(data,label,test_size=0.3)
	for i  in range(1,100):
	    knn=KNeighborsClassifier(n_neighbors=i)
	    # 传入model X,y  折叠次数  判断精确度
	    score=cross_val_score(knn,X_train,y_train,cv=5,scoring='accuracy')
	    # 返回每组测试的成绩
	    print(score)

在这里插入图片描述
如果对score取平均score.mean()就得到我们想要的结果了:
在这里插入图片描述
为了更直观的看出区别,我们使用画图的方法,将其画出来:

	k_range=range(1,100)
	k_score=[]
	for k  in k_range:
	    knn=KNeighborsClassifier(n_neighbors=k)
	    # 传入model X,y  折叠次数  判断精确度
	    loss=-cross_val_score(knn,data,label,cv=10,scoring='neg_mean_squared_error')#for regression 偏差
    	score=cross_val_score(knn,data,label,cv=10,scoring='accuracy')#for classfier 
	    # 返回每组测试的成绩
	    k_score.append(score.mean())
	plt.plot(k_range,k_score)
	plt.show()

在这里插入图片描述

想测试哪种model性能更好,可以在for循环中,改变model


存储

训练好的model我们需要把它存储下来

  1. pickle
  2. joblib
	from sklearn.datasets import  load_iris
	from  sklearn.neighbors import  KNeighborsClassifier
	knn=KNeighborsClassifier()
	X,y=load_iris()
	knn.fit(X,y)
	
	import  pickle
	# 存储
	with open('save/clf.pickle','wb') as f:
	    pickle.dump(knn,f)
	
	with open('save/clf.pickle','rb') as f:
	    pickle.load(f)
	
	from  sklearn.externals import joblib
	# 存储
	joblib.dump(knn,'save/clf.job')
	# 读取
	joblib.load('save/clf.job')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值