这篇文章主要讲两个事:
- 给大家介绍一下机器学习中的一个简单算法-K近邻算法
- 科普一个冷门专业——选矿
今天借助一些选矿的数据来讲一下这个算法。
选矿是干什么的?选矿就是研究如何从矿石中把有用的矿物提取出来的一门学科。选矿之前要先把矿石弄成粉末,让矿石中的有用矿物和其他杂质分开,然后再利用有用矿物和其他杂志之间的物理化学性质差异将它们分开。
我们今天使用的这些数据是关于磁铁矿的,在这个磁铁矿山中,开采出来的原矿石里面有很多杂质,黄铁矿、赤铁矿、石英、云母、绿泥石、伊利石……偶尔还能发现价值连城的天然绿松石……
下面简单介绍一下数据含义:
- BallMillAbility:球磨机台时能力,可以理解为每台机器每小时磨出来的矿粉的量;
- OreGrade:原矿品位,也就是原矿中的铁元素含量;
- RateofMagnet:磁铁率,即在所有铁矿物(磁铁矿、黄铁矿、赤铁矿、褐铁矿等)中磁铁矿所占的比例;
- TailGrade:尾矿品位,尾矿就是选矿之后产生的渣渣;
- ConcentrateGrade:精矿品位,就是选矿的最终产品,这个指标在选矿厂是严格控制的,一般波动只有1%。64%品位的磁铁精矿意味着磁铁矿含量已经达到了88%。
我们今天做的预测模型就是要通过这前面4个指标来预测第5个指标能否达标
读取csv文件:
In [1]:import pandas as pd
In [2]:df = pd.read_csv('D://Practice/Data.csv')
In [3]:df
Out[3]:
BallMillAbility OreGrade RateofMagnet TailGrade ConcentrateGrade
0 297.76 18.98 71.65 8.30 64.35
1 280.15 18.68 73.39 8.59 64.87
2 302.81 18.23 72.13 8.69 64.76
3 173.41 19.55 74.42 9.00 64.57
4 345.66 18.57 75.93 9.28 64.62
5 312.65 18.34 72.19 9.19 64.38
6 306.85 17.80 71.80 9.35 64.50
.. ... ... ... ... ...
预测指标处理
将最后一列提取出来,作为每一列的分类标签(其中64.5以上为合格(1),64.5以下为不合格(0))
for i in range(149):
if df['ConcentrateGrade'][i] >= 64.5:
df['ConcentrateGrade'][i] = 1
else:
df['ConcentrateGrade'][i] = 0
Out[13]:
BallMillAbility OreGrade RateofMagnet TailGrade ConcentrateGrade
0 297.76 18.98 71.65 8.30 0.0
1 280.15 18.68 73.39 8.59 1.0
2 302.81 18.23 72.13 8.69 1.0
3 173.41 19.55 74.42 9.00 1.0
4 345.66 18.57 75.93 9.28 1.0
5 312.65 18.34 72.19 9.19 0.0
6 306.85 17.80 71.80 9.35 1.0
.. ... ... ... ... ...
预留的预测样本(这里只留了一个,实际使用的时候需要较多数据):
BallMillAbility OreGrade RateofMagnet TailGrade ConcentrateGrade
340.22 17.08 66.66 9.30 --
计算距离并按距离排序
求这一点到数据集中各点的距离,并将这个距离值作为一列新的数据加入到df中。
df['Distance'] = 0
from numpy import *
for i in range(149):
distance = sqrt((df['BallMillAbility'][i]-350.22)**2+(df['OreGrade'][i]-17.08)**2+(df['RateofMagnet'][i]-65.65)**2+(df['TailGrade'][i]-10.30)**2)
df['Distance'][i] = distance
排序
a = df.sort(columns = 'Distance')#这里记住对调用df的sort方法不会对df做出改变。
BallMillAbility OreGrade RateofMagnet TailGrade ConcentrateGrade Distance
99 349.90 17.44 68.06 8.50 0.0 3
40 349.49 17.03 69.76 8.49 0.0 4
10 352.13 17.41 70.53 8.82 1.0 5
100 351.63 18.48 71.81 8.46 1.0 6
65 355.82 16.92 70.51 7.52 0.0 7
104 347.20 18.76 71.59 8.75 0.0 7
113 350.17 18.75 73.23 9.04 0.0 7
46 352.35 18.13 71.98 8.18 0.0 7
.. ... ... ... ... ...
预测
然后取前k个值(我们取20),统计前k个值中1占多少。
b = a.reset_index(drop = True)#这里要重新建立索引,以便后续操作。另:使用a的reset_index方法不会改变a的值
m = 0
for i in range(20):
if b['ConcentrateGrade'][i] == 1:
m += 1
In[46]:m
Out[46]: 9
可见前20组数据中,ConcentrateGrade小于64.5的占多数,我们继续加大k的值试试:
k 20 30 40 50
m 3 6 10 12
通过测试结果我们可以判定,这趟指标应该不会合格。
在做预测模型的时候,为了避免数据量纲对模型的影响,我们会对数据进行归一化处理
数据归一化处理
这里采用最简单的现象函数归一化(Min-Max Scaling)
p = min(df['BallMillAbility'])
o = max(df['BallMillAbility'])
for i in range(149):
df['BallMillAbility'][i] = (df['BallMillAbility'][i]-p)/(o-p)
就这样依次把4列数据都归一化
Out[33]:
BallMillAbility OreGrade RateofMagnet TailGrade ConcentrateGrade
0 0.508755 0.526555 0.418244 0.325203 0.0
1 0.436707 0.481032 0.567986 0.443089 1.0
2 0.529417 0.412747 0.459552 0.483740 1.0
3 0.000000 0.613050 0.656627 0.609756 1.0
4 0.704730 0.464340 0.786575 0.723577 1.0
5 0.569675 0.429439 0.464716 0.686992 0.0
6 0.545946 0.347496 0.431153 0.752033 1.0
7 0.305294 0.391502 0.555077 0.609756 0.0
8 0.594509 0.335357 0.444062 0.776423 1.0
9 0.506505 0.074355 0.302926 0.691057 1.0
.. ... ... ... ... ...
归一化处理完了之后别忘记保存一下
df.to_csv('D://Practice/data1.csv')
然后我们再用k近邻算法计算一遍得到如下结果:
k 20 30 40 50
m 3 9 19 31
这样又出现了不同的结果,理论上来讲,归一化之后的预测模型应该更加准确一点。
ps:对选矿有兴趣的可以私信我