当前位置: 首页 > 后端技术 > Python

机器学习笔记(一)——KNN泰坦尼克号生存记录建模的两种方法

时间:2023-03-26 14:57:38 Python

KNN算法原理)的工作原理是:有一个样本数据集,称为训练样本集,样本集中的每一个数据有一个标签,即样本集中的每个数据与其所属类别的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据的对应特征进行比较,然后算法提取样本中特征最相似(最近距离)的数据的分类标签放。如图,图中绿点的label是未知的,但是已知它要么属于蓝色正方形要么属于红色三角形,如何判断它属于哪一边呢?kNN算法的核心思想是,如果一个样本在特征空间中的k个最近邻样本中的大部分属于某一类,则该样本也属于这一类,并具有该类样本的特征。上图实线圆圈中,有两个红色三角形,只有一个蓝色正方形,所以是红色三角形的可能性较大;但是在虚线圆圈中,有两个红色三角形和三个蓝色方块,那么它就越有可能是蓝色方块;所以对于kNN算法来说,k的取值不同,结果可能不同,k的取值在很大程度上决定了模型的准确率。KNN算法采集数据步骤:爬虫,开放数据源数据清洗:处理缺失值,不相关特征导入数据,转化为结构化数据格式数据归一化,标准化计算距离(最常见的是欧式距离)和距离升序排序,取前K判断测试数据属于哪一类,计算模型的准确率。KNN算法实现了Pclass、Sex、Age、SibSp、Parch这五个特征会对标签Survived产生较大的影响。Age列有缺失值。这里我们使用Median(中位数),也可以选择mean(均值)填充。数据获取:泰坦尼克号生存数据方法1首先我们需要导入数据,将DataFrame转换成矩阵,将标签存入列表'''Survived:1为生存,0为死亡Sex:1为男性,0为femalepclass:cabinclasssibsp:配偶、兄弟姐妹数parch:父母、子女数'''#打开文件,导入数据deffile(path):#打开文件data=pd.read_csv(path)#ConvertDataFrame对于矩阵feature_matrix=array(data.iloc[:,1:6])label=[]foriindata['Survived']:label.append(i)returnfeature_matrix,标签多维数组转为矩阵后期对于数据的Normalization非常友好,将label存储在list中。当比较真实结果和预测结果时,指标很简单。k-NN算法的核心步骤是计算两者之间的距离,距离排序,类别统计。本文使用欧几里德距离公式具体作用如下#计算距离defclassify(test_data,train_data,label,k):Size=train_data.shape[0]#复制每行测试数据的Size次减去训练数据,水平复制Size次,垂直复制一次the_matrix=tile(test_data,(Size,1))-train_data#对减法得到的结果进行平方sq_the_matrix=the_matrix**2#平方和,axis=1表示水平all_the_matrix=sq_the_matrix.sum(axis=1)#Result开平方得到最终的距离distance=all_the_matrix**0.5#将距离从小到大排序,结果为索引sort_distance=distance.argsort()dis_Dict={}#Getthefirstkforiinrange(k):#获取前K个labelsthe_label=label[sort_distance[i]]#将label的key和value引入字典dis_Dict[the_label]=dis_Dict.get(the_label,0)+1#根据value的大小对字典进行排序,从大到小,即就是,在K范围内,生存和死亡的数量sort_Count=sorted(dis_Dict.items(),key=operator.itemgetter(1),reverse=True)returnsort_Count[0][0]numpy有一个tile方法是可以将一个一维矩阵横向复制几次,纵向复制几次,所以一个测试数据经过tile方法处理后,减去训练数据,得到新的矩阵后,对每块求平方和添加矩阵中的数据(水平)并打开根标志。可以得到测试数据和每条训练数据之间的距离。接下来就是将所有的距离按升序排列,取前K个距离,在这个范围内,统计1(生存)0(死亡)类别的个数,返回出现次数多的类别的标签。在该数据中,就Age列而言,数据分布在0-80之间,而在其他特征中,数据分布在0-3之间。相比之下,Age特征的权重比较大,所以在计算距离的时候,需要进行归一化处理,否则大数会吃小数。归一化公式:x'=(x-X_min)/(X_max-X_min)#归一化defnormalize(train_data):#得到训练矩阵中的最小值和最大值min=train_data.min(0)max=train_data.max(0)#最大值和最小值的范围ranges=max-min#训练数据减去最小值normalmatrix=train_data-tile(min,(train_data.shape[0],1))#除以最大值和最小值的范围values得到归一化数据normalmatrix=normalmatrix/tile(ranges,(train_data.shape[0],1))#返回归一化数据结果,数据范围,最小值returnnormalmatrix该函数返回一个特征矩阵,所有数据分布在0-1,不会有偏见。最后一步:划分数据集,取9个作为训练数据集,取1个作为测试数据集,将预测结果与真实结果进行比较,计算模型的准确率,代码如下:#testdatadefTest():#打开文件名path="Titanic.csv"#返回特征矩阵和特征标签feature_matrix,label=file(path)#返回归一化的特征矩阵normalmatrix=normalize(feature_matrix)#得到归一化后的矩阵numberofrowsm=normalmatrix.shape[0]#取所有数据的百分之十num=m//10correct=0.0foriinrange(num):#前num个数据作为测试集,num-m数据作为训练集classifierResult=classify(normalmatrix[i,:],normalmatrix[num:m,:],label[num:m],9)#比较预测结果和真实结果print("预测结果:%d\tTrueresult:%d"%(classifierResult,label[i]))ifclassifierResult==label[i]:correct+=1.0print("正确率:{:.2f}%".format(correct/浮动(数字)*100))#程序结束时间,并输出程序运行时间end=time.time()print(str(end-start))代码部分结束,代码运行截图如下。不同K值对应的模型准确率如下:69.66%75.28%73.03%74.16%73.03%77.53%77.53%79.78%77.53%部分数据分析从上图可以得出以下结论得出:第三舱的遇难者人数最多,幸存者人数很少;第二舱遇难者年龄分布较广,但幸存者年龄较小;虽然第一舱的遇难者人数最少,而且大多数是老年人,但舱级更为重要。女性的总体存活率高于男性。性高得多——这里有真爱法两部分代码如下:#计算距离defdistance(d1,d2):res=0forkeyin('Pclass','Sex','Age','SibSp','Parch'):#每行数据成对相减计算距离res+=(float(d1[key])-float(d2[key]))**2returnres**0.5#KNN算法defKNN(data,train_data):data_list=[#只保留Survived和data的距离({'result':train['Survived'],'distance':distance(data,train)})fortrainintrain_data]#根据距离的大小对list进行排序data_list=sorted(data_list,key=lambdaitem:item['distance'])#得到第K个data_list2=data_list[0:K]result_list=[]#判断在K的范围内,哪边是测试数据更倾向于iindata_list2:m=i['result']result_list.append(m)sum_1=0sum_0=0foriinresult_list:ifi=='1':sum_1+=1else:sum_0+=1ifsum_1>sum_0:return'1'else:return'0'第二种方法主要是用字典的方式读取并对数据进行统计,与第一种方法的特征矩阵不同,但是是千变万化的,算法的核心思想是一样的代码运行截图如下:方法一K值最终取9,方法二K值最终取8,两种方法相比,方法一的建模精度更高,程序运行时间也更短,个人认为方法二使用了字典知识更容易理解,而方法一使用了更多的矩阵知识。公众号“奶糖猫”在后台回复“泰坦尼克号”获取源码和数据供参考,感谢大家的支持。