感悟:
First将原始数据通过直观的图表形式反应出来。
Second因为使用的核心算法是欧几里得距离公式。为了避免较大的数值对公式影响,要让数据框中的每一个属性都雨露均沾,所以都转化成百分比,各个属性的权重也就都一样了。这叫做归一化。
Third将我们的数据集划分训练集和测试集(测试集删除它的标签)。
Forth构建分类器,作用就是给测试集的数据打上标签,返回新的测试集
最后
print(datingClass(train, test, 5)) # 通过train来predict我们的test,5代表距离最近的5个点来决定test某个点(某条数据)的标签
修改pip3的镜像源问题
https://www.jianshu.com/p/6b02411a9713
安装pandas和numpy和matplotlib包
pip3 install matplotlib
pip3 install pandas
pip3 install numpy
解决中文方框框和乱码显示问题——plt.rcParams[‘font.sans-serif’] = [‘SimHei’]
http://www.mamicode.com/info-detail-2693409.html?__cf_chl_jschl_tk__=de62c25180d55a0068a90d14e324fd751eb5c9a3-1584271943-0-AX0kEq8FeUfA_RhZ1LLqONMaUo1z5aI-6PaV_kq4xaX0bNSYEhHtgjJ841pZG3blu-r8GGsZzbA_W5ix2MOPQ03i-czzbt9CDBsd1OT1_4AsM6chIbyXheKR-XnaqFqnoIc5LYZTcO6uocXute7qo0_rrUOwoMxo4mf-54h5mbdOOZb5QI3J2SXSBDcnKprX7u1M4No_NG3BSRLq5CjiAgeHyOp77OxaujPJGrT_KxNdE86hMCzlxlSPUjuRPTCNcBd2iArUwEu4iSQTNkl5wVean_B4bGwCeaMcctUUUf2tRpdR8WipzDZ1Tz7pGp5iog
PyCharm里面的c、m、F、f、v、p 含义
https://www.cnblogs.com/paulwinflo/p/12201137.html
KNN编程问题理解:
使用pandas库的语法分析器(panda.io.parser)读入文件,默认源文件是以空格为分隔符的文件形式存在的,然后使用类型为dataframe的一个变量进行存储读入的数据。
import pandas as pd
datingSet = pd.read_table("datingTestSet.txt", header=None)
print(datingSet)
输出datingSet变量的前5行数据
print(datingSet.head())
print是与类和实例无关的函数(与类和实例有关的叫做方法)
datingSet是数据框类型的变量,它的property(datingSet看做对象,shape看做其一个变量吧)
Index:索引
Ops:开源插件规范
Mixin: 混合类型
print(datingSet.shape)
返回基础数据外貌的一个元组类型(元组的说法:数据库的一条记录也是一个元组等等说法)
print(datingSet.info())
类型:数据框类型
索引范围:1000条条目,#:0-999
数据列数:4列
Non-Null:非空
Dtype:datatype
内存使用:31.4+KB
把不同标签用颜色区分,Color是一个list(存储任意数据类型)
Color = []
range是一个(builtins)内置的范围类,我们传入参数即可。
iloc是dataframe的property,可取行可取列,可改变其数据类型,进去有其定义和用法。
for i in range(datingSet.shape[0]):
m = datingSet.iloc[i, -1]
if m == "didntLike":
Color.append('black')
if m == "largeDoses":
Color.append('red')
if m == "smallDoses":
Color.append('orange')
# print(type(Color))
# print(Color)
绘制两点之间的散点图
rcParams里面的rc:
run configuration
plt.scatter()函数用于生成一个scatter散点图。
scatter部分参数说明:
x,y:表示的是shape大小为(n,)的数组,也就是我们即将绘制散点图的数据点,输入数据
marker:MarkerStyle,表示的是标记的样式,可选,默认’o’
c:表示的是色彩或颜色序列,可选,默认蓝色’b’。但是c不应该是一个单一的RGB数字,也不应该是一个RGBA的序列,因为不便区分。c可以是一个RGB或RGBA二维行数组
plt.rcParams['font.sans-serif'] = ['SimHei'] # 图中字体设置为黑色 允许后面中文显示
# 归一化函数:使各属性权重相等
def minmax(dataSet):
minDf = dataSet.min()
maxDf = dataSet.max()
normSet = (dataSet - minDf) / (maxDf - minDf)
return normSet
# 将我们的数据集带入函数,进行归一化处理
datingT = pd.concat([minmax(datingTest.iloc[:, :3]), datingTest.iloc[:, 3]], axis=1) # minmiax将除去第三列的数据返回成数据框
print(type(datingT))
print(datingT.head())
iloc相关切割参考如下:
https://blog.csdn.net/weixin_42138078/article/details/80275326
完整代码:
import matplotlib as mpl
import pandas as pd
import matplotlib.pyplot as plt
# 约会网站配对效果
# 导入数据集
datingTest = pd.read_table('datingTestSet.txt', header=None)
# print(datingTest)
print(datingTest.head())
print(datingTest.shape)
print(datingTest.info())
# 分析数据
# 使用matplotlib创建散点图,查看各数据的分布情况
# %matplotlib inline
# 把不同标签用颜色区分
Colors = []
for i in range(datingTest.shape[0]):
m = datingTest.iloc[i, -1]
if m == 'didntLike':
Colors.append('black')
if m == 'smallDoses':
Colors.append('orange')
if m == 'largeDoses':
Colors.append('red')
# 绘制两两特征之间的散点图
plt.rcParams['font.sans-serif'] = ['SimHei'] # 图中字体设置为黑色 允许后面中文显示
pl = plt.figure(figsize=(12, 8)) # 设置画布
fig1 = pl.add_subplot(221)
plt.scatter(datingTest.iloc[:, 1], datingTest.iloc[:, 2], marker='.', c=Colors)
plt.xlabel('玩游戏视频所占时间比')
plt.ylabel('每周消费冰淇淋公升数')
fig2 = pl.add_subplot(222)
plt.scatter(datingTest.iloc[:, 0], datingTest.iloc[:, 1], marker='.', c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('玩游戏视频所占时间比')
fig3 = pl.add_subplot(223)
plt.scatter(datingTest.iloc[:, 0], datingTest.iloc[:, 2], marker='.', c=Colors)
plt.xlabel('每年飞行常客里程')
plt.ylabel('每周消费冰淇淋公升数')
plt.show()
# 归一化函数:使各属性权重相等
def minmax(dataSet):
minDf = dataSet.min()
maxDf = dataSet.max()
normSet = (dataSet - minDf) / (maxDf - minDf)
return normSet
# 将我们的数据集带入函数,进行归一化处理
datingT = pd.concat([minmax(datingTest.iloc[:, :3]), datingTest.iloc[:, 3]], axis=1) # minmiax将除去第三列的数据返回成数据框
print(type(datingT))
print(datingT.head())
# 4.划分训练集和测试集
def randSplit(dataSet, rate=0.9):
n = dataSet.shape[0]
m = int(n * rate)
train = dataSet.iloc[:m, :]
test = dataSet.iloc[m:, :]
test.index = range(test.shape[0]) # 重置index行号
return train, test
train, test = randSplit(datingT)
print(train)
print(test)
# 5.构建分类器
def datingClass(train, test, k):
n = train.shape[1] - 1
m = test.shape[0]
result = []
for i in range(m):
dist = list((((train.iloc[:, :n] - test.iloc[i, :n]) ** 2).sum(1)) ** 0.5) # 欧几里得距离函数
dist_l = pd.DataFrame({'dist': dist, 'labels': (train.iloc[:, n])}) # 将训练集(原始已知标签的数据)与当前测试集的某条数据求欧氏距离
dr = dist_l.sort_values(by='dist')[:k] # 将已知标签的数据与需要测试的某条数据求出的欧氏距离进行排序,从小到大,找到最接近测试数据的临近的原始数据
re = dr.loc[:, 'labels'].value_counts() # 对某条测试数据临近的原始数据进行标签统计
result.append(re.index[0]) # 给这条测试数据打上标签
result = pd.Series(result) # 将result的类型从列表转换成数据框格式,方便后面的数据框整合
test['predict'] = result # 在测试数据级后面替加一列predict放刚才的预测结果,也就是rest与result的数据框格式的整合
# 下面这一行有警告,难顶
acc = (test.iloc[:, -1] == test.iloc[:, -2]).mean() # 求均值函数(妙啊,如果某行两个属性不等为0,等为1,然后求和的结果在除以总数)
print(f'模型预测准确率为{acc}') # 格式化输出
return test # 这里的test已经是处理完成的结果了
# 验证模型
print(datingClass(train, test, 5)) # 通过train来predict我们的test,5代表距离最近的5个点来决定test某个点(某条数据)的标签