机器学习入门整理
内容总结来自网课和部分博客,代码数据集来自中国大学mooc北理的机器学习课程,大赞这个课程。
使用到的数据集文件:
链接:https://pan.baidu.com/s/1BoSx797rsF9CKj9pvA2bzw
提取码:x8l7
一、无监督学习-聚类
聚类就是对大量未知标注的数据集,按照数据内部存在的数据特征将数据集划分为多个不同的类别,使类别内的数据比较相似,类别之间的数据相似度比较小,属于无监督学习。聚类算法的重点是计算样本项之间的相似度,有时候也称为样本间的距离。
1.K-means算法
K-means算法以k为参数,将n个对象分为k个簇,使得每个簇本身内部有较高的相似度,而簇间的相似度较低。
算法逻辑步骤:
(1)随机选择k个点作为初始的聚类中心。
(2)对于剩下的点,根据其与聚类中心的距离,将其归入最近的簇。
(3)对每个簇,计算所有点的均值作为新的聚类中心。
(4)重复2、3直到聚类中心不再发生改变。
图解:
应用:
数据介绍:
现有1999年全国31个省份城镇居民家庭平均每人全年消费性支出的八个主要变量数据,这八个变量分别是:食品、衣着、家庭设备用品及服务、医疗 保健、交通和通讯、娱乐教育文化服务、居住以及杂项商品和服务。利用已有数据,对31个省份进行聚类。
实验目的:
通过聚类,了解1999年各个省份的消费水平在国内的情况。
代码:
#导入sklearn相关包以及cluster下的Kmeans算法模块
import numpy as np
from sklearn.cluster import KMeans
def loadData(filePath):
fr = open(filePath,'r+')
lines = fr.readlines()
retData = []
retCityName = []
for line in lines:
items = line.strip().split(",")
retCityName.append(items[0])
retData.append([float(items[i]) for i in range(1,len(items))])
return retData,retCityName
if __name__ == '__main__':
# 利用loadData方法读取数据
data,cityName = loadData('city.txt')
# 创建实例
km = KMeans(n_clusters=4)
# 调用Kmeans()fit_predict()方法进行计算
label = km.fit_predict(data)
expenses = np.sum(km.cluster_centers_,axis=1)
print('聚类中心个数:',len(expenses))
# 将城市按label分成设定的簇
CityCluster = [[],[],[],[]]
# 将每个簇的城市输出
for i in range(len(cityName)):
print('当前城市',cityName[i],'对应data在聚类后label为:',label[i])
CityCluster[label[i]].append(cityName[i])
# 将每个簇的平均花费输出
for i in range(len(CityCluster)):
print("Expenses:%.2f" % expenses[i])
print(CityCluster[i])
2.K中心点算法
为了减轻k均值算法对孤立点的敏感性,k中心点算法不采用簇中对象的平均值作为簇中心,而选用簇中离平均值最近的对象作为簇中心。
k中心算法的基本过程是:首先为每个簇随意选择一个代表对象,剩余的对象根据其与每个代表对象的距离分配给最近的代表对象所代表的簇;然后反复用非代表对象来代替代表对象,以优化聚类质量。聚类质量用一个代价函数来表示。当一个中心点被某个非中心点替代时,除了未被替换的中心点外,其余各点被重新分配。
K中心点算法可以看做是K均值算法的一种改进。
算法逻辑步骤:
(1)随机选择k个代表对象作为初始的中心点
(2)指派每个剩余对象给离它最近的中心点所代表的簇
(3)随机地选择一个非中心点对象y
(4)计算用y代替中心点x的总代价s
(5)如果s为负,则用可用y代替x,形成新的中心点
(6)重复(2)(3)(4)(5),直到k个中心点不再发生变化。
3.DBSCAN算法
DBSCAN算法是一种基于密度的聚类算法:
• 核心点:在半径Eps内含有超过MinPts数目的点
• 边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内
• 噪音点:既不是核心点也不是边界点的点
算法逻辑步骤:
(1)将所有点标记为核心点、边界点或噪声点;
(2)删除噪声点;
(3)为距离在Eps之内的所有核心点之间赋予一条边;
(4)每组连通的核心点形成一个簇;
(5)将每个边界点指派到一个与之关联的核心点的簇中(哪一个核心点的半
径范围之内)。
应用:
数据介绍:
现有大学校园网的日志数据,290条大学生的校园网使用情况数据,数据包
括用户ID,设备的MAC地址,IP地址,开始上网时间,停止上网时间,上
网时长,校园网套餐等。利用已有数据,分析学生上网的模式。
实验目的:
通过DBSCAN聚类,分析学生上网时间和上网时长的模式。
代码:
#分析学生开始上网时间和上网时长的模式
#单个学生上网日志(记录编号、学生编号、MAC地址、IP地址、开始、停止上网时间、上网时长)
#1.建立工程,引入sklearn相关包
import numpy as np
import sklearn.cluster as skc
from sklearn import metrics
import matplotlib.pyplot as plt
#2.加载数据,预处理数据
#读取每条数据中的mac地址,开始上网时间,上网时长
mac2id=dict()
onlineTimes=[]
f=open('TestData.txt',encoding='utf-8')#注意编码方式
for line in f:
mac=line.split(',')[2]
startTime=int(line.split(',')[4].split()[1].split(':')[0])#要用int 不能eval
onlineTime=int(line.split(',')[6])#读取每条数据的mac地址,开始上网时间,上网时长
if mac not in mac2id:#mac2id字典中键为mac地址,值为对应mac地址的上网时间和上网时长
mac2id[mac]=len(onlineTimes)
onlineTimes.append((startTime,onlineTime))
else:
onlineTimes[mac2id[mac]]=[(startTime,onlineTime)]
#2.1上网时间聚类,创建DBSCAN,进行训练,获得标签
real_X=np.array(onlineTimes).reshape(-1,2)#变换成n行2列维度的数组
X=real_X[:,0:1]#提取每行的第一列数,即startTime
db=skc.DBSCAN(eps=0.01,min_samples=20).fit(X)
labels=db.labels_
print('Labels:%s'%labels)#输出数据被记上的标签
#计算噪声数据(标签为-1)的比例
ratio=len(labels[labels[:]==-1])/len(labels)
#labels[:]==-1生成一个布尔数组,labels[labels[:]==-1]挑出原labels内为-1的元素
print('Noise ratio:{:.2%}'.format(ratio)) #要加:
#计算簇的个数(先把labels变为集合,集合无重复,计算总label个数,减去噪声label)
n_clusters_=len(set(labels))-(1 if -1 in labels else 0)
print('Estimated number of cluster:%d'%n_clusters_)
#评价聚类效果
print('Silhouette Coefficient:%0.3f'%metrics.silhouette_score(X,labels))
#输出各簇标号及簇内数据
for i in range(n_clusters_):
print('Cluster',i,':')
print(list(X[labels==i].flatten()))#array.flatten()为折叠成一维数组
#直方图展示,分析结果
plt.subplot(121)
plt.hist(X,24)
plt.xlabel('上网时间')
plt.ylabel('上网时长')
plt.axis([0,25,0,70])
#2.2上网时长聚类,创建DBSCAN,进行训练,获得标签
Y=np.log(1+real_X[:,1:])
db=skc.DBSCAN(eps=0.14,min_samples=10).fit(Y)
labels=db.labels_
print('Labels_Y:%s'%labels)
ratio=len(labels[labels[:]==-1])/len(labels)
print('Noise ratio:{:.2%}'.format(ratio))
n_clusters_=len(set(labels))-(1 if -1 in labels else 0)
print('Estimated number of cluster:%d'%n_clusters_)
print('Silhouette Coefficient:%0.3f'%metrics.silhouette_score(Y,labels))
#统计每一个簇内的样本个数,均值,标准差
for i in range(n_clusters_):
print('Cluster',i,':')
count=len(Y[labels==i])
mean=np.mean(real_X[labels==i][:,1])
std=np.std(real_X[labels==i][:,1])
print('\t number of sample:%d'%count)
print('\t mean of sample :%.2f'%mean)
print('\t std of sample :{:.2f}'.format(std))
plt.subplot(122)
plt.subplots_adjust(wspace=0.3)#调整subplots之间横向间距,纵向用hspace
x=np.linspace(0,len(labels),len(labels))
plt.plot(x,real_X[:,1])
二、监督学习-分类
1.SVM支持向量机
支持向量机方法是建立在统计学习理论的VC维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折中,以期获得最好的推广能力。
算法逻辑步骤:
算法的原理和逻辑步骤相当复杂,感兴趣可以阅读文献、查阅博客等,建议阅读《机器学习》-周志华著。
应用:
数据介绍:
股票数据,包括开盘价、收盘价等等常见指标。
实验目的:
预测股票涨跌。
代码:
import pandas as pd
import numpy as np
# 导入SVM模块
from sklearn import svm
# 导入交叉验证
from sklearn import cross_validation
# 读取数据集文件
data=pd.read_csv('stock/000777.csv',encoding='gbk',parse_dates=[0],index_col=0)
data.sort_index(0,ascending=True,inplace=True)
# data.shape[0]-dayfeature,训练需要的是当天的前150天的所有五项股市指标,所以如果数据集为200,则只有后50条有前150天
# 5*dayfeature是因为取的是五项指标
# featurenum+1是额外增加了当天的开盘价这个指标与featurenum个150*5指标共同构成当天的特征
dayfeature=150
featurenum=5*dayfeature
x=np.zeros((data.shape[0]-dayfeature,featurenum+1))
y=np.zeros((data.shape[0]-dayfeature))
for i in range(0,data.shape[0]-dayfeature):
x[i,0:featurenum]=np.array(data[i:i+dayfeature] \
[[u'收盘价',u'最高价',u'最低价',u'开盘价',u'成交量']]).reshape((1,featurenum))
x[i,featurenum]=data.ix[i+dayfeature][u'开盘价']
# 收盘价如果大于开盘价是涨则记为1,小于则跌了记为0
for i in range(0,data.shape[0]-dayfeature):
if data.ix[i+dayfeature][u'收盘价']>=data.ix[i+dayfeature][u'开盘价']:
y[i]=1
else:
y[i]=0
clf=svm.SVC(kernel='rbf')
result = []
for i in range(5):
#划分交叉验证的 数据集 训练集 ,测试集比例20%
x_train, x_test, y_train, y_test = \
cross_validation.train_test_split(x, y, test_size = 0.2)
clf.fit(x_train, y_train)
result.append(np.mean(y_test == clf.predict(x_test)))
# 打印准确率
print("svm classifier accuacy:")
print(result)
2.K近邻分类(KNN)
通过计算待分类数据点,与已有数据集中的所有数据点的距离。取距离最小的前K个点,根据“少数服从多数“的原则,将这个数据点划分为出现次数最多的那个类别。
算法逻辑步骤:
(1)计算测试数据与各个训练数据之间的距离;
(2)按照距离的递增关系进行排序;
(3)选取距离最小的K个点;
(4)确定前K个点所在类别的出现频率;
(5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
3.决策树
决策树是一种树形结构的分类器,通过顺序 询问分类点的属性决定分类点最终的类别。通常根据特征的信息增益或其他指标,构建一颗决策 树。在分类时,只需要按照决策树中的结点依次 进行判断,即可得到样本所属类别。
算法逻辑步骤:
建议参阅《机器学习》-周志华著。
4.朴素贝叶斯
朴素贝叶斯分类器是一个以贝叶斯定理为基础 的多分类的分类器。
对于给定数据,首先基于特征的条件独立性假设,学习输入输出的联合概率分布,然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。
算法逻辑步骤:
建议参阅《机器学习》-周志华著。
KNN&决策树&朴素贝叶斯的应用:
数据介绍:
我们现在收集了来自 A,B,C,D,E 5位用户的可穿戴设备上的传感器数据, 每位用户的数据集包含一个特征文件(a.feature)和一个标签文件(a.label)。
特征文件中每一行对应一个时刻的所有传感器数值,标签文件中每行记录了 和特征文件中对应时刻的标记过的用户姿态,两个文件的行数相同,相同行之间互相对应。
实验目的:
使用经典的分类算法,如K近邻、决策树和朴素贝叶斯对运动数据做运动状态分类。
KNN&决策树&朴素贝叶斯代码:
import pandas as pd
import numpy as np
from sklearn.preprocessing import Imputer
from sklearn.cross_validation import train_test_split
from sklearn.metrics import classification_report
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
def load_datasets(feature_paths, label_paths):
feature = np.ndarray(shape=(0,41))
label = np.ndarray(shape=(0,1))
for file in feature_paths:
df = pd.read_table(file, delimiter=',', na_values='?', header=None)
imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
imp.fit(df)
df = imp.transform(df)
feature = np.concatenate((feature, df))
for file in label_paths:
df = pd.read_table(file, header=None)
label = np.concatenate((label, df))
label = np.ravel(label)
return feature, label
if __name__ == '__main__':
''' 数据路径 '''
featurePaths = ['A/A.feature','B/B.feature','C/C.feature','D/D.feature','E/E.feature']
labelPaths = ['A/A.label','B/B.label','C/C.label','D/D.label','E/E.label']
''' 读入数据 '''
x_train,y_train = load_datasets(featurePaths[:4],labelPaths[:4])
x_test,y_test = load_datasets(featurePaths[4:],labelPaths[4:])
x_train, x_, y_train, y_ = train_test_split(x_train, y_train, test_size = 0.0)
print('Start training knn')
knn = KNeighborsClassifier().fit(x_train, y_train)
print('Training done')
answer_knn = knn.predict(x_test)
print('Prediction done')
print('Start training DT')
dt = DecisionTreeClassifier().fit(x_train, y_train)
print('Training done')
answer_dt = dt.predict(x_test)
print('Prediction done')
print('Start training Bayes')
gnb = GaussianNB().fit(x_train, y_train)
print('Training done')
answer_gnb = gnb.predict(x_test)
print('Prediction done')
print('\n\nThe classification report for knn:')
print(classification_report(y_test, answer_knn))
print('\n\nThe classification report for DT:')
print(classification_report(y_test, answer_dt))
print('\n\nThe classification report for Bayes:')
print(classification_report(y_test, answer_gnb))
三、无监督学习-回归
1.线性回归
线性回归(Linear Regression)是利用数理统计中回归分析, 来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。
线性回归利用称为线性回归方程的最小平方函数对一个或多个自 变量和因变量之间关系进行建模。这种函数是一个或多个称为回 归系数的模型参数的线性组合。只有一个自变量的情况称为简单回归,大于一个自变量情况的叫做多元回归。
算法逻辑步骤:
(1)使用形如y=wTx+b 的线性模型拟合数据输入和输出之间的映射关系。
(2)求取w与b。
应用:
数据介绍:
与房价密切相关的除了单位的房价,还有房屋的尺寸。我们可以根据已知的房屋成交价和房屋的尺寸进行线性回归,继而可以对已知房屋尺寸,而未知房屋成交价格的实例进行成交价格的预测。
实验目的:
对房屋成交信息建立线性回归方程,并依据回归方程对房屋价格进行预测
代码:
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
# 读取数据集
datasets_X = []
datasets_Y = []
fr = open('prices.txt','r')
lines = fr.readlines()
for line in lines:
items = line.strip().split(',')
datasets_X.append(int(items[0]))
datasets_Y.append(int(items[1]))
length = len(datasets_X)
datasets_X = np.array(datasets_X).reshape([length,1])
datasets_Y = np.array(datasets_Y)
minX = min(datasets_X)
maxX = max(datasets_X)
X = np.arange(minX,maxX).reshape([-1,1])
# 创建线性分类器
linear = linear_model.LinearRegression()
linear.fit(datasets_X, datasets_Y)
# 图像中显示
# 绘制样本散点图
plt.scatter(datasets_X, datasets_Y, color = 'red')
plt.plot(X, linear.predict(X), color = 'blue')
plt.xlabel('Area')
plt.ylabel('Price')
plt.show()
2.多项式回归
多项式回归(Polynomial Regression)是研究一个因变量与一个或多个自变量间多项式的回归分析方法。如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称为多元多项式回归。
算法逻辑步骤:
(1)多项式回归是使用曲线拟合数据的输入与输出的映射关系。
(2)求取多项式展开项每项的系数
应用:
数据介绍:
与房价密切相关的除了单位的房价,还有房屋的尺寸。我们可以根据已知的房屋成交价和房屋的尺寸进行线性回归,继而可以对已知房屋尺寸,而未知房屋成交价格的实例进行成交价格的预测。
实验目的:
对房屋成交信息建立多项式回归方程,并依据回归方程对房屋价格进行预测
代码:
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
# 读取数据集
datasets_X = []
datasets_Y = []
fr = open('prices.txt','r')
lines = fr.readlines()
for line in lines:
items = line.strip().split(',')
datasets_X.append(int(items[0]))
datasets_Y.append(int(items[1]))
length = len(datasets_X)
datasets_X = np.array(datasets_X).reshape([length,1])
datasets_Y = np.array(datasets_Y)
minX = min(datasets_X)
maxX = max(datasets_X)
X = np.arange(minX,maxX).reshape([-1,1])
poly_reg = PolynomialFeatures(degree = 2)
X_poly = poly_reg.fit_transform(datasets_X)
lin_reg_2 = linear_model.LinearRegression()
lin_reg_2.fit(X_poly, datasets_Y)
# 图像中显示
plt.scatter(datasets_X, datasets_Y, color = 'red')
plt.plot(X, lin_reg_2.predict(poly_reg.fit_transform(X)), color = 'blue')
plt.xlabel('Area')
plt.ylabel('Price')
plt.show()