吴恩达ML课程课后总结,以供复习、总结、温故知新,也欢迎诸位评论讨论分享,一起探讨一起进步:
上一篇:机器学习(6)--SVM使用sklearn模块python实现(附练习数据资源文件百度云)https://blog.csdn.net/qq_36187544/article/details/88377748
下一篇:机器学习(8)--PCA算法及python中sklearn模块实现https://blog.csdn.net/qq_36187544/article/details/88394909
上数据资源与源代码:
链接:https://pan.baidu.com/s/1YlTDOHqDDNjLZadhZrGsuQ
提取码:4gyd
raw.txt是美国人口普查数据原集,train.txt是从中取100行的数据为了实现K均值,07.py是源码
进入正题,现在到了无监督学习,主要就是聚类算法,就是没有对应的y输出,将数据集分类,比如将人群分类等, 比如市场收集了关于衣服身高和体重的数据,想划分大中小号,就可以用k=3的K均值算法
K-Means算法,k均值算法(每次都要被这些算法的思想所惊艳到)。
核心思想是,先随机确定K个聚类中心,然后将聚类附近的点划分到聚类中心所属簇,计算当前簇的平均值,将聚类中心移动到平均值处,再次循环,划分聚类中心所属簇,计算均值,移动聚类中心。。。最终当聚类中心不再移动时,得到合适的分类集。如下左图,随机初始化两个点(两个×,将数据划分到两个×对应的簇里),计算平均值移动两个聚类中心(下中图),重新聚类(如下右图),直到中心不再改变。
详细算法:
1.初始化K值,确定几个聚类中心,并随机化,直接用几个样本点作为初始化值
2.重复循环:(1)聚类,计算距离每个点到每个聚类中心的二范数平方即距离,取最小,认为当前点属于该聚类中心。(2)移动聚类中心
注:如果存在某个聚类中心一个点都没有,一般做法是移除该点,若非要K个聚类中心,可重新随机初始化聚类中心计算
优化目标:为了让算法更优,避免陷入局部最优解,提出优化目标,失真代价函数(畸变函数)如下图, J是所有点到该聚类中心二范数平方和的均值。就是从数学的角度再解释了一下点划分到最近的簇,为了让代价函数最小。
如何避开局部最优:初始随机化时直接用几个样本点作为聚类中心,除此之外,多次随机(次数一般在50-1000次)是必不可少的(这只针对K在2-10范围内,若太大,多次随机能稍微改变分类结果,但效果不明显)
如何选择聚类数量?手动选择。
一种思路:绘制横坐标为K聚类数量,纵坐标为J畸变函数的图像,像一个手肘,选择肘部那个点(下左图),肘部法则,如果没有清晰拐点(下右图),随便选一个合适的罗。
另一种思路:通过实际来确定K聚类数量,是需要更精确的划分还是更划算的划分。
数据来源于人口普查,特征数量过多,取两个,方便平面可视化。
取100组数据,绘制如下,由于数据都为整点,所以看起来可能会有些许奇怪,由于重叠显示看起来不多:
最后运行分类结果为,大点为聚类中心:
源码如下:
import numpy as np
import matplotlib.pyplot as plt
import random
# 求二范数方
def get2(x1,x2,y1,y2):
return pow(x1-y1,2)+pow(x2-y2,2)
# K-means,这里让k=2吧
def k_means(x1,x2):
c1,c2 = random.randint(0,99),random.randint(0,99)
len_x = len(x1)
center1,center2= [x1[c1],x2[c1]],[x1[c2],x2[c2]] # 聚类中心
for iii in range(1000):
center1_cluster, center2_cluster = [], []# 属于不同聚类中心的集合
for i in range(len_x):
if get2(center1[0],center1[1],x1[i],x2[i]) > get2(center2[0],center2[1],x1[i],x2[i]):
center2_cluster.append(i)
else:center1_cluster.append(i)
sum1,sum2=0,0
for i in range(len(center1_cluster)):
sum1+=x1[center1_cluster[i]]
sum2+=x2[center1_cluster[i]]
center1[0]=sum1/len(center1_cluster)
center1[1]=sum2/len(center1_cluster)
sum1, sum2 = 0, 0
for i in range(len(center2_cluster)):
sum1 += x1[center2_cluster[i]]
sum2 += x2[center2_cluster[i]]
center2[0] = sum1 / len(center2_cluster)
center2[1] = sum2 / len(center2_cluster)
return [center1_cluster,center2_cluster,center1,center2] # 转为list传回,center1_cluster里存的是Index,在把中心传回绘制
x1, x2 = [],[]
for sample in open("census1990_train.txt", "r"):
# 原始数据太多需要占位
a1,_x1,a2,a3,a4,a5,_x2,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a40,a41,a42,a43,a44,a45,a46,a47,a48,a49,a50,a51,a52,a53,a54,a55,a56,a57,a58,a59,a60,a61,a62,a63,a64,a65,a66,a67 = sample.split(",")
x1.append(float(_x1))
x2.append(float(_x2))
x1, x2 = np.array(x1), np.array(x2) # 转化为Numpy数组待处理
# print(x1)
# print(x2)
plt.figure()
plt.xlabel("age(10)")
plt.ylabel("class")
re_list = k_means(x1,x2)
# 第一簇绘制
x1_1,x1_2=[],[]
for i in range(len(re_list[0])):
x1_1.append(x1[re_list[0][i]])
x1_2.append(x2[re_list[0][i]])
plt.scatter(x1_1, x1_2, c="r", s=6) #s是点的大小,c是颜色‘b’blue‘g’green‘r’red‘c’cyan‘m’magenta‘y’yellow‘k’black‘w’white
plt.scatter(re_list[2][0], re_list[2][1], c="r", s=36)
print("红色聚类中心:"+str(re_list[2][0])+","+str(re_list[2][1]))
# print(x1_1)
# print(x1_2)
# 第一簇绘制
x2_1,x2_2=[],[]
for i in range(len(re_list[1])):
x2_1.append(x1[re_list[1][i]])
x2_2.append(x2[re_list[1][i]])
plt.scatter(x2_1, x2_2, c="b", s=6)
plt.scatter(re_list[3][0], re_list[3][1], c="b", s=36)
print("蓝色聚类中心:"+str(re_list[3][0])+","+str(re_list[3][1]))
plt.show()