赞
踩
全部的代码、数据集见我github
DryBean数据集传不上github,放在了CSDN,0积分即可下载:Drybean下载
选定Iris数据集作为计算样例,取K=7、欧式距离、30%测试集、70%训练集、随机种子0
步骤
1.对每个特征值采用数据归一化。采用min-max归一化方法,公式为(X-Min)/(Max-Min)
2.对于第一个测试样本来说,计算其到训练集中所有样本的欧式距离
3.选择最小的前K个距离,进行投票,按照少数服从多数得到这个样本的预测标签
4.计算下一个测试样本的标签,直到做完全部预测
#导入包
%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from scipy.spatial import distance
import operator
#引入数据集 iriis = datasets.load_iris() x= iriis.data y= iriis.target #数据集归一(线性归一化) x= (x-x.min(axis=0)) / (x.max(axis=0)-x.min(axis=0)) #axis=0表示取列的最大值或者最小值 #拆分训练集和测试集 split = 0.7 #trianset : testset = 7:3 np.random.seed(0) #固定随机结果 train_indices = np.random.choice(len(x),round(len(x) * split),replace=False) test_indices = np.array(list(set(range(len(x))) - set(train_indices)))
train_indices = sorted(train_indices)
test_indices =sorted(test_indices)
train_x = x[train_indices]
test_x = x[test_indices]
train_y = y[train_indices]
test_y = y[test_indices]
print(train_indices)
print(test_indices)
[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 20, 22, 24, 26, 27, 30, 33, 37, 38, 40, 41, 42, 43, 44, 45, 46, 48, 50, 51, 52, 53, 54, 56, 59, 60, 61, 62, 63, 64, 66, 68, 69, 71, 73, 76, 78, 80, 83, 84, 85, 86, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 100, 101, 102, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 116, 119, 120, 121, 123, 124, 125, 126, 127, 128, 129, 132, 133, 134, 135, 137, 139, 141, 143, 144, 146, 147, 148, 149]
[0, 9, 14, 19, 21, 23, 25, 28, 29, 31, 32, 34, 35, 36, 39, 47, 49, 55, 57, 58, 65, 67, 70, 72, 74, 75, 77, 79, 81, 82, 87, 88, 99, 103, 115, 117, 118, 122, 130, 131, 136, 138, 140, 142, 145]
pd.DataFrame(train_x).head(10)
#与excel的计算结果一致
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 0.166667 | 0.416667 | 0.067797 | 0.041667 |
1 | 0.111111 | 0.500000 | 0.050847 | 0.041667 |
2 | 0.083333 | 0.458333 | 0.084746 | 0.041667 |
3 | 0.194444 | 0.666667 | 0.067797 | 0.041667 |
4 | 0.305556 | 0.791667 | 0.118644 | 0.125000 |
5 | 0.083333 | 0.583333 | 0.067797 | 0.083333 |
6 | 0.194444 | 0.583333 | 0.084746 | 0.041667 |
7 | 0.027778 | 0.375000 | 0.067797 | 0.041667 |
8 | 0.305556 | 0.708333 | 0.084746 | 0.041667 |
9 | 0.138889 | 0.583333 | 0.101695 | 0.041667 |
## KNN
from sklearn.neighbors import KNeighborsClassifier #一个简单的模型,只有K一个参数,类似K-means
from sklearn.model_selection import train_test_split,cross_val_score #划分数据 交叉验证
k_range = range(1,10) #k是投票人数
cv_scores = [] #用来放每个模型的结果值
for n in k_range:
knn = KNeighborsClassifier(n) #knn模型,这里一个超参数可以做预测,当多个超参数时需要使用另一种方法GridSearchCV
scores = cross_val_score(knn,train_x,train_y,cv=10,scoring='accuracy') #cv:选择每次测试折数 accuracy:评价指标是准确度,可以省略使用默认值,具体使用参考下面。
cv_scores.append(scores.mean())
plt.plot(k_range,cv_scores)
plt.xlabel('K')
plt.ylabel('Accuracy') #通过图像选择最好的参数
plt.show()
best_knn = KNeighborsClassifier(n_neighbors=7) # 选择最优的K=7传入模型
best_knn.fit(train_x,train_y) #训练模型
print(best_knn.score(test_x,test_y)) #score = right/total = 44/45 = 0.9778(这里预测错了一个)
print(best_knn.predict(test_x))
print(test_y)
0.9777777777777777
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 2 2 2 2
2 2 2 2 2 2 2 2]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
2 2 2 2 2 2 2 2]
不需要训练、没有参数估计,拿到测试数据即可进行分类
当样本中每种类型的数量不均衡时,可能会强行“少数服从多数”
#依旧是7:3划分数据集
#均衡Iris:7:3 = 105:45 = (33+34+38):(17+16+12) (使用之前划分的数据集)
#不均衡Iris:7:3 = 105:45 = (45+45+15):(5+5+35)
#均衡DryBean:7:3 = 1960:840 =(280*7):(120*7)
#不均衡DryBean:7:3 = 1960:840 = (6:6:6:6:6:4:3) =
#(318,318,318,318,318,212,159):(68,91,136,136,136,136,136)
from numpy import *
i_train_x = train_x
i_train_y = train_y
i_test_x = test_x
i_test_y = test_y
ui_train_x = concatenate((concatenate((x[:45],x[50:95]),axis=0),x[100:115]),axis=0) #axis=0表示竖向拼接
ui_train_y = concatenate((concatenate((y[:45],y[50:95]),axis=0),y[100:115]),axis=0)
ui_test_x = concatenate((concatenate((x[:5],x[50:55]),axis=0),x[100:135]),axis=0)
ui_test_y = concatenate((concatenate((y[:5],y[50:55]),axis=0),y[100:135]),axis=0)
i_score = [] ui_score = [] klist = [] for k in range(1,12): klist.append(k) i_knn = KNeighborsClassifier(n_neighbors=k) i_knn.fit(i_train_x,i_train_y) i_score.append(i_knn.score(i_test_x,i_test_y)) # print("均衡Iris:",i_knn.score(i_test_x,i_test_y)) ui_knn = KNeighborsClassifier(n_neighbors=k) ui_knn.fit(ui_train_x,ui_train_y) ui_score.append(ui_knn.score(ui_test_x,ui_test_y)) # print("不均衡Iris:",i_knn.score(ui_test_x,ui_test_y)) plt.plot(klist, i_score, marker = 'o', label = 'banlanced Iris') plt.plot(klist, ui_score,marker = '*', label = 'unbalanced Iris') plt.legend() #让图例生效 plt.xlabel('k-value') plt.ylabel('accuracy-value') plt.title(u'Iris map') plt.show()
# import openpyxl
import operator
from sklearn.preprocessing import StandardScaler # 均值归一化
from sklearn.metrics import confusion_matrix # 生成混淆矩阵
from sklearn.metrics import classification_report # 分类报告
def openfile(filename):
"""
打开数据集,进行数据处理
:param filename:文件名
:return:特征集数据、标签集数据
"""
# 打开excel
sheet = pd.read_excel(filename,sheet_name='Dry_Beans_Dataset')
data = sheet.iloc[:,:16].values
target = sheet['Class'].values
print(data.shape)
print(target.shape)
return data, target, sheet.columns
def split_data_set(data_set, target_set, rate=0.7): """ 说明:分割数据集,默认数据集的30%是测试集 :param data_set: 数据集 :param target_set: 标签集 :param rate: 测试集所占的比率 :return: 返回训练集数据、训练集标签、测试集数据、测试集标签 """ # 计算训练集的数据个数 train_size = len(data_set) # 随机获得数据的下标 train_index = sorted(np.random.choice(train_size,round(train_size * rate), replace=False)) test_index = sorted(np.array(list(set(range(train_size)) - set(train_index)))) #不用排序也行,强迫症,为了上面保持一致就排序了 # 分割数据集(X表示数据,y表示标签) x_train = data_set.iloc[train_index,:] #因为这里的data_set和target_set变成DataFrame,而不是ndarray了,所以要用iloc访问 x_test = data_set.iloc[test_index,:] y_train = target_set.iloc[train_index,:] y_test = target_set.iloc[test_index,:] return x_train, y_train, x_test, y_test
filename = r'D:\jjq\code\jupyterWorkSpace\datasets\DryBeanDataset\Dry_Bean_Dataset.xlsx'
o_bean_dataset = openfile(filename)
#每个类别的种子抽取400条数据,这个是每个类别的起始索引
step = 400
start_index = [0,1322,1844,3474,7020,8948,10975] #一共7类
# bean_dataset_x = pd.DataFrame(columns=o_bean_dataset[2])
# bean_dataset_y =pd.DataFrame(columns=o_bean_dataset[2])
bean_dataset_x = pd.DataFrame(columns=range(16))
bean_dataset_y =pd.DataFrame(columns=range(1))
bean_dataset_x.drop(bean_dataset_x.index,inplace=True)
bean_dataset_y.drop(bean_dataset_y.index,inplace=True)
for i in range(7):
bean_dataset_x = pd.concat((bean_dataset_x, pd.DataFrame(o_bean_dataset[0][start_index[i]:(step+start_index[i])])),axis=0)
bean_dataset_y = pd.concat((bean_dataset_y, pd.DataFrame(o_bean_dataset[1][start_index[i]:(step+start_index[i])])),axis=0)
# bean_dataset_y.to_excel("./123.xlsx")
(13611, 16)
(13611,)
#按照均衡和不均衡的方式,划分训练集和测试集 #均衡 b_train_x, b_train_y, b_test_x, b_test_y = split_data_set(bean_dataset_x,bean_dataset_y) print(b_train_x.shape,b_train_y.shape) print(b_test_x.shape,b_test_y.shape) #不均衡 steps_train = [318,318,318,318,318,212,159] steps_test = [68,91,136,136,136,136,136] now = 0 #初始化不均衡数组 ub_train_x = pd.DataFrame(columns=range(16)) ub_test_x = pd.DataFrame(columns=range(16)) ub_train_y = pd.DataFrame(columns=range(1)) ub_test_y = pd.DataFrame(columns=range(1)) #保证添加数据之前数组为空 ub_train_x.drop(ub_train_x.index,inplace=True) ub_test_x.drop(ub_test_x.index,inplace=True) ub_train_y.drop(ub_train_y.index,inplace=True) ub_test_y.drop(ub_test_y.index,inplace=True) #开始添加数据 for i in range(7): ub_train_x = pd.concat((ub_train_x, bean_dataset_x[now:(now+steps_train[i])]),axis=0) ub_train_y = pd.concat((ub_train_y, bean_dataset_y[now:(now+steps_train[i])]),axis=0) now = now+steps_train[i] ub_test_x = pd.concat((ub_test_x, bean_dataset_x[now:(now+steps_test[i])]),axis=0) ub_test_y = pd.concat((ub_test_y, bean_dataset_y[now:(now+steps_test[i])]),axis=0) now = now+steps_test[i]
(1960, 16) (1960, 1)
(840, 16) (840, 1)
b_score = [] ub_score = [] klist = [] for k in range(30,50): klist.append(k) b_knn = KNeighborsClassifier(n_neighbors=k) b_knn.fit(b_train_x,b_train_y.values.ravel()) b_score.append(b_knn.score(b_test_x,b_test_y.values.ravel())) ub_knn = KNeighborsClassifier(n_neighbors=k) ub_knn.fit(ub_train_x,ub_train_y.values.ravel()) ub_score.append(ub_knn.score(ub_test_x,ub_test_y.values.ravel())) plt.plot(klist, b_score, marker = 'o', label = 'banlanced DryBean') plt.plot(klist, ub_score,marker = '*', label = 'unbalanced DryBean') plt.legend() #让图例生效 plt.xlabel('k-value') plt.ylabel('accuracy-value') plt.title(u'DryBean map') plt.show()
#这里放一下手动实现算法的代码,并且做到和调包的正确率一样
#采用Iris数据集作为计算样例
print(type(train_x))
print(pd.DataFrame(train_x).shape)
print(train_x[0][1])
<class 'numpy.ndarray'>
(105, 4)
0.41666666666666663
#定义KNN类,用于分类,类中定义两个预测方法,分为考虑权重不考虑权重两种情况 class KNN: ''' 使用Python语言实现K近邻算法。(实现分类) ''' def __init__(self, k): '''初始化方法 Parameters ----- k:int 邻居的个数 ''' self.k = k def fit(self,X,y): '''训练方法 Parameters ---- X : 类数组类型,形状为:[样本数量, 特征数量] 待训练的样本特征(属性) y : 类数组类型,形状为: [样本数量] 每个样本的目标值(标签)。 ''' #将X转换成ndarray数组 self.X = np.asarray(X) self.y = np.asarray(y) def predict(self,X): """根据参数传递的样本,对样本数据进行预测。 Parameters ----- X : 类数组类型,形状为:[样本数量, 特征数量] 待训练的样本特征(属性) Returns ----- result : 数组类型 预测的结果。 """ X = np.asarray(X) result = [] # 对ndarray数组进行遍历,每次取数组中的一行。 for x in X: # 对于测试集中的每一个样本,依次与训练集中的所有样本求距离。 dis = np.sqrt(np.sum((x - self.X) ** 2, axis=1)) ## 返回数组排序后,每个元素在原数组(排序之前的数组)中的索引。 index = dis.argsort() # 进行截断,只取前k个元素。【取距离最近的k个元素的索引】 index = index[:self.k] # 返回数组中每个元素出现的次数。元素必须是非负的整数。【使用weights考虑权重,权重为距离的倒数。】 if dis[index].all()!=0: count = np.bincount(self.y[index], weights= 1 / dis[index]) else : pass # 返回ndarray数组中,值最大的元素对应的索引。该索引就是我们判定的类别。 # 最大元素索引,就是出现次数最多的元素。 result.append(count.argmax()) return np.asarray(result)
#创建KNN对象,进行训练与测试。
knn = KNN(k=7)
#进行训练
knn.fit(train_x,train_y)
#进行测试
result = knn.predict(test_x)
# display(result)
# display(test_y)
display(np.sum(result == test_y))
if len(result)!=0:
display(np.sum(result == test_y)/ len(result))
#与调包结果一致
44
0.9777777777777777
# Code source: Gaël Varoquaux # Andreas Müller # Modified for documentation by Jaques Grobler # License: BSD 3 clause import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.datasets import make_moons, make_circles, make_classification from sklearn.neural_network import MLPClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC from sklearn.gaussian_process import GaussianProcessClassifier from sklearn.gaussian_process.kernels import RBF from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier from sklearn.naive_bayes import GaussianNB from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis h = 0.02 # step size in the mesh names = [ "Nearest Neighbors", "Linear SVM", "RBF SVM", "Gaussian Process", "Decision Tree", "Random Forest", "Neural Net", "AdaBoost", "Naive Bayes", "QDA", ] classifiers = [ KNeighborsClassifier(3), SVC(kernel="linear", C=0.025), SVC(gamma=2, C=1), GaussianProcessClassifier(1.0 * RBF(1.0)), DecisionTreeClassifier(max_depth=5), RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1), MLPClassifier(alpha=1, max_iter=1000), AdaBoostClassifier(), GaussianNB(), QuadraticDiscriminantAnalysis(), ] X, y = make_classification( n_features=2, n_redundant=0, n_informative=2, random_state=1, n_clusters_per_class=1 ) rng = np.random.RandomState(2) X += 2 * rng.uniform(size=X.shape) linearly_separable = (X, y) datasets = [ make_moons(noise=0.3, random_state=0), make_circles(noise=0.2, factor=0.5, random_state=1), linearly_separable, ] figure = plt.figure(figsize=(27, 9)) i = 1 # iterate over datasets for ds_cnt, ds in enumerate(datasets): # preprocess dataset, split into training and test part X, y = ds X = StandardScaler().fit_transform(X) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.4, random_state=42 ) x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5 y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) # just plot the dataset first cm = plt.cm.RdBu cm_bright = ListedColormap(["#FF0000", "#0000FF"]) ax = plt.subplot(len(datasets), len(classifiers) + 1, i) if ds_cnt == 0: ax.set_title("Input data") # Plot the training points ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, edgecolors="k") # Plot the testing points ax.scatter( X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6, edgecolors="k" ) ax.set_xlim(xx.min(), xx.max()) ax.set_ylim(yy.min(), yy.max()) ax.set_xticks(()) ax.set_yticks(()) i += 1 # iterate over classifiers for name, clf in zip(names, classifiers): ax = plt.subplot(len(datasets), len(classifiers) + 1, i) clf.fit(X_train, y_train) score = clf.score(X_test, y_test) # Plot the decision boundary. For that, we will assign a color to each # point in the mesh [x_min, x_max]x[y_min, y_max]. if hasattr(clf, "decision_function"): Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()]) else: Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1] # Put the result into a color plot Z = Z.reshape(xx.shape) ax.contourf(xx, yy, Z, cmap=cm, alpha=0.8) # Plot the training points ax.scatter( X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, edgecolors="k" ) # Plot the testing points ax.scatter( X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, edgecolors="k", alpha=0.6, ) ax.set_xlim(xx.min(), xx.max()) ax.set_ylim(yy.min(), yy.max()) ax.set_xticks(()) ax.set_yticks(()) if ds_cnt == 0: ax.set_title(name) ax.text( xx.max() - 0.3, yy.min() + 0.3, ("%.2f" % score).lstrip("0"), size=15, horizontalalignment="right", ) i += 1 plt.tight_layout() plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。