机器学习十大算法与案例实现
监督学习1. 线性回归梯度下降一元线性回归 import numpy as npimport matplotlib.pyplot as plt# 载入数据data = np.genfromtxt('data.csv', delimiter=',')x_data = data[:,0]y_data = data[:,1]# 学习率learning ratelr = 0.0001# 截距b = 0 # 斜率k = 0 # 最大迭代次数epochs = 50# 最小二乘法def compute_error(b, k, x_data, y_data): totalError = 0 for i in range(0, len(x_data)): totalError += (y_data[i] - (k * x_data[i] + b)) ** 2 return totalError / float(len(x_data)) / 2.0def gradient_descent_runner(x_data, y_data, b, k, lr, epochs): # 计算总数据量 m = float(len(x_data)) # 循环epochs次 for i in range(epochs): b_grad = 0 k_grad = 0 # 计算梯度的总和再求平均 for j in range(0, len(x_data)): b_grad += (1/m) * (((k * x_data[j]) + b) - y_data[j]) k_grad += (1/m) * x_data[j] * (((k * x_data[j]) + b) - y_data[j]) # 更新b和k b = b - (lr * b_grad) k = k - (lr * k_grad) return b, kprint('Starting b = {0}, k = {1}, error = {2}'.format(b, k, compute_error(b, k, x_data, y_data)))print('Running...')b, k = gradient_descent_runner(x_data, y_data, b, k, lr, epochs)print('After {0} iterations b = {1}, k = {2}, error = {3}'.format(epochs, b, k, compute_error(b, k, x_data, y_data)))#画图plt.plot(x_data, y_data, 'b.')plt.plot(x_data, k*x_data + b, 'r')plt.show() ![]() 梯度下降法-多元线性回归
![]() 2.逻辑回归逻辑回归原理与推导 import matplotlib.pyplot as pltimport numpy as npfrom sklearn.metrics import classification_reportfrom sklearn import preprocessing# 数据是否需要标准化scale = True# 载入数据data = np.genfromtxt('LR-testSet.csv', delimiter=',')x_data = data[:,:-1]y_data = data[:,-1] def plot(): x0 = [] x1 = [] y0 = [] y1 = [] # 切分不同类别的数据 for i in range(len(x_data)): if y_data[i]==0: x0.append(x_data[i,0]) y0.append(x_data[i,1]) else: x1.append(x_data[i,0]) y1.append(x_data[i,1]) # 画图 scatter0 = plt.scatter(x0, y0, c='b', marker='o') scatter1 = plt.scatter(x1, y1, c='r', marker='x') #画图例 plt.legend(handles=[scatter0,scatter1],labels=['label0','label1'],loc='best') plot()#查看数据plt.show() ![]()
![]() # 预测def predict(x_data, ws): if scale == True: x_data = preprocessing.scale(x_data) xMat = np.mat(x_data) ws = np.mat(ws) return [1 if x >= 0.5 else 0 for x in sigmoid(xMat*ws)]predictions = predict(X_data, ws)print(classification_report(y_data, predictions)) ![]() 梯度下降法-非线性逻辑回归
![]() # 定义多项式回归,degree的值可以调节多项式的特征poly_reg = PolynomialFeatures(degree=3) # 特征处理x_poly = poly_reg.fit_transform(x_data)def sigmoid(x): return 1.0/(1+np.exp(-x))def cost(xMat, yMat, ws): left = np.multiply(yMat, np.log(sigmoid(xMat*ws))) right = np.multiply(1 - yMat, np.log(1 - sigmoid(xMat*ws))) return np.sum(left + right) / -(len(xMat))def gradAscent(xArr, yArr): if scale == True: xArr = preprocessing.scale(xArr) xMat = np.mat(xArr) yMat = np.mat(yArr) lr = 0.03 epochs = 50000 costList = [] # 计算数据列数,有几列就有几个权值 m,n = np.shape(xMat) # 初始化权值 ws = np.mat(np.ones((n,1))) for i in range(epochs+1): # xMat和weights矩阵相乘 h = sigmoid(xMat*ws) # 计算误差 ws_grad = xMat.T*(h - yMat)/m ws = ws - lr*ws_grad if i % 50 == 0: costList.append(cost(xMat,yMat,ws)) return ws,costList# 训练模型,得到权值和cost值的变化ws,costList = gradAscent(x_poly, y_data)print(ws)# 获取数据值所在的范围x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))# np.r_按row来组合array, # np.c_按colunm来组合array# >>> a = np.array([1,2,3])# >>> b = np.array([5,2,5])# >>> np.r_[a,b]# array([1, 2, 3, 5, 2, 5])# >>> np.c_[a,b]# array([[1, 5],# [2, 2],# [3, 5]])# >>> np.c_[a,[0,0,0],b]# array([[1, 0, 5],# [2, 0, 2],# [3, 0, 5]])z = sigmoid(poly_reg.fit_transform(np.c_[xx.ravel(), yy.ravel()]).dot(np.array(ws)))# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据for i in range(len(z)): if z[i] > 0.5: z[i] = 1 else: z[i] = 0z = z.reshape(xx.shape)# 等高线图cs = plt.contourf(xx, yy, z)plot() plt.show() ![]()
![]() 3.神经网络神经网络 4. SVM支持向量机SVM-非线性 import matplotlib.pyplot as pltimport numpy as npfrom sklearn.metrics import classification_reportfrom sklearn import svm# 载入数据data = np.genfromtxt('LR-testSet2.txt', delimiter=',')x_data = data[:,:-1]y_data = data[:,-1] def plot(): x0 = [] x1 = [] y0 = [] y1 = [] # 切分不同类别的数据 for i in range(len(x_data)): if y_data[i]==0: x0.append(x_data[i,0]) y0.append(x_data[i,1]) else: x1.append(x_data[i,0]) y1.append(x_data[i,1]) # 画图 scatter0 = plt.scatter(x0, y0, c='b', marker='o') scatter1 = plt.scatter(x1, y1, c='r', marker='x') #画图例 plt.legend(handles=[scatter0,scatter1],labels=['label0','label1'],loc='best') plot()plt.show()# fit the model# C和gammamodel = svm.SVC(kernel='rbf')model.fit(x_data, y_data)model.score(x_data,y_data)# 获取数据值所在的范围x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))z = model.predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据z = z.reshape(xx.shape)# 等高线图cs = plt.contourf(xx, yy, z)plot() plt.show() ![]() 5. K邻近主要过程 ![]() ![]()
![]() 6. 贝叶斯 设每个数据样本用一个n维特征向量来描述n个属性的值,即:X={x1,x2,…,xn},假定有m个类,分别用C1, C2,…,Cm表示。给定一个未知的数据样本X(即没有类标号),若朴素贝叶斯分类法将未知的样本X分配给类Ci,则一定是 P(Ci|X)>P(Cj|X) 1≤j≤m,j≠i from sklearn.naive_bayes import GaussianNBfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import accuracy_scorefrom sklearn.preprocessing import LabelEncoderimport pandas as pdfrom numpy import *import operator#计算高斯分布密度函数的值def calculate_gaussian_probability(mean, var, x): coeff = (1.0 / (math.sqrt((2.0 * math.pi) * var))) exponent = math.exp(-(math.pow(x - mean, 2) / (2 * var))) c= coeff * exponent return c#计算均值def averagenum(num): nsum = 0 for i in range(len(num)): nsum += num[i] return nsum / len(num)#计算方差def var(list,avg): var1=0 for i in list: var1+=float((i-avg)**2) var2=(math.sqrt(var1/(len(list)*1.0))) return var2#朴素贝叶斯分类模型def Naivebeys(splitData, classset, test): classify = [] for s in range(len(test)): c = {} for i in classset: splitdata = splitData[i] num = len(splitdata) mu = num + 2 character = len(splitdata[0])-1 #具体数据集,个数有变 classp = [] for j in range(character): zi = 1 if isinstance(splitdata[0][j], (int, float)): numlist=[example[j] for example in splitdata] Mean=averagenum(numlist) Var=var(numlist,Mean) a = calculate_gaussian_probability(Mean, Var, test[s][j]) else: for l in range(num): if test[s][j] == splitdata[l][j]: zi += 1 a=zi/mu classp.append(a) zhi = 1 for k in range(character): zhi *= classp[k] c.setdefault(i, zhi) sorta = sorted(c.items(), key=operator.itemgetter(1), reverse=True) classify.append(sorta[0][0]) return classify#评估def accuracy(y, y_pred): yarr=array(y) y_predarr=array(y_pred) yarr = yarr.reshape(yarr.shape[0], -1) y_predarr = y_predarr.reshape(y_predarr.shape[0], -1) return sum(yarr == y_predarr) / len(yarr)#数据处理def splitDataset(dataSet): #按照属性把数据划分 classList = [example[-1] for example in dataSet] classSet = set(classList) splitDir = {} for i in classSet: for j in range(len(dataSet)): if dataSet[j][-1] == i: splitDir.setdefault(i, []).append(dataSet[j]) return splitDir, classSet open('test.txt')df = pd.read_csv('test.txt')class_le = LabelEncoder()dataSet = df.values[:, :]dataset_train,dataset_test=train_test_split(dataSet, test_size=0.1)splitDataset_train, classSet_train = splitDataset(dataset_train)classSet_test=[example[-1] for example in dataset_test]y_pred= Naivebeys(splitDataset_train, classSet_train, dataset_test)accu=accuracy(classSet_test,y_pred)print('Accuracy:', accu) Accuracy: 0.65 7. 决策树 决策树的分类模型是树状结构,简单直观,比较符合人类的理解方式。决策树分类器的构造不需要任何领域知识和参数设置,适合于探索式知识的发现。由于决策树分类步骤简单快速,而且一般来说具有较高的准确率,因此得到了较多的使用。 ![]() ![]() 数据集介绍 ![]() 实验
导入数据 def load_dataset(): # 数据集文件所在位置 path = './西瓜.csv' data = pd.read_csv(path, header=0) dataset = [] for a in data.values: dataset.append(list(a)) # 返回数据列表 attribute = list(data.keys()) # 返回数据集和每个维度的名称 return dataset, attributedataset,attribute = load_dataset()attribute,dataset
计算信息熵 def calculate_info_entropy(dataset): # 记录样本数量 n = len(dataset) # 记录分类属性数量 attribute_count = {} # 遍历所有实例,统计类别出现频次 for attribute in dataset: # 每一个实例最后一列为类别属性,因此取最后一列 class_attribute = attribute[-1] # 如果当前类标号不在label_count中,则加入该类标号 if class_attribute not in attribute_count.keys(): attribute_count[class_attribute] = 0 # 类标号出现次数加1 attribute_count[class_attribute] += 1 info_entropy = 0 for class_attribute in attribute_count: # 计算该类在实例中出现的概率 p = float(attribute_count[class_attribute]) / n info_entropy -= p * log2(p) return info_entropy 数据集划分
计算属性划分数据集的熵 def calculate_attribute_entropy(dataset,i,values): attribute_entropy = 0 for value in values: sub_dataset = split_dataset(dataset,i,value) p = len(sub_dataset) / float(len(dataset)) attribute_entropy += p*calculate_info_entropy(sub_dataset) return attribute_entropy 计算信息增益
根据信息增益进行划分 def split_by_info_gain(dataset): # 描述属性数量 attribute_num = len(dataset[0]) - 1 # 整个数据集的信息熵 info_entropy = calculate_info_entropy(dataset) # 最高的信息增益 max_info_gain = 0 # 最佳划分维度属性 best_attribute = -1 for i in range(attribute_num): info_gain = calculate_info_gain(dataset,info_entropy,i) if(info_gain > max_info_gain): max_info_gain = info_gain best_attribute = i return best_attribute 构造决策树
{'纹理': {'清晰': {'根蒂': {'蜷缩': '是', '硬挺': '否', '稍蜷': {'色泽': {'青绿': '是', '乌黑': {'触感': {'软粘': '否', '硬滑': '是'}}}}}}, '模糊': '否', '稍糊': {'触感': {'软粘': '是', '硬滑': '否'}}}}
# 计算叶结点数def get_num_leaf(tree): numLeafs = 0 firstStr = list(tree.keys())[0] secondDict = tree[firstStr] for key in secondDict.keys(): if type(secondDict[key]).__name__ == 'dict': numLeafs += get_num_leaf(secondDict[key]) else: numLeafs += 1 return numLeafs
# 绘制文本框def plot_text(cntrPt, parentPt, txtString): xMid = (parentPt[0] - cntrPt[0]) / 2.0 + cntrPt[0] yMid = (parentPt[1] - cntrPt[1]) / 2.0 + cntrPt[1] createPlot.ax1.text(xMid, yMid, txtString, va='center', ha='center', rotation=30) 绘制树结构
# 绘制箭头def plotNode(nodeTxt, centerPt, parentPt, nodeType): createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', xytext=centerPt, textcoords='axes fraction', va='center', ha='center', bbox=nodeType, arrowprops=arrow)
#指定默认字体mpl.rcParams['font.sans-serif'] = ['SimHei']mpl.rcParams['axes.unicode_minus'] = False# 绘制决策树createPlot(tree) ![]() 8. 集成学习(Adaboost) 集成学习(Ensemble Learning),就是使用一系列学习器进行学习,并使用某种规则将各个学习器的结果进行整合,从而获得比单个学习器效果更好的学习效果的一种方法。 集成学习的条件 通过集成学习提高分类器的整体泛化能力有以下两个条件:
![]() 集成学习的两个关键点:
构建差异性分类器一般有以下三种方法:
集成学习常见的三种元算法是Bagging, Boosting和Stacking。Bagging用于提升机器学习算法的稳定性和准确性。Boosting主要用于减少bias(偏差)和variance(方差),是将一个弱分类器转化为强分类器的算法。Stacking是一种组合多个模型的方法。 ![]() ![]() Boosting与AdaBoost算法的训练 Boosting分类方法,其过程如下所示: 1)先通过对N个训练数据的学习得到第一个弱分类器h1; 2)将h1分错的数据和其他的新数据一起构成一个新的有N个训练数据的样本,通过对这个样本的学习得到第二个弱分类器h2; 3)将h1和h2都分错了的数据加上其他的新数据构成另一个新的有N个训练数据的样本,通过对这个样本的学习得到第三个弱分类器h3; 4)最终经过提升的强分类器h_final=Majority Vote(h1,h2,h3)。即某个数据被分为哪一类要通过h1,h2,h3的多数表决。 上述Boosting算法,存在两个问题: ①如何调整训练集,使得在训练集上训练弱分类器得以进行。 ②如何将训练得到的各个弱分类器联合起来形成强分类器。 针对以上两个问题,AdaBoost算法进行了调整: ①使用加权后选取的训练数据代替随机选取的训练数据,这样将训练的焦点集中在比较难分的训练数据上。 ②将弱分类器联合起来时,使用加权的投票机制代替平均投票机制。让分类效果好的弱分类器具有较大的权重,而分类效果差的分类器具有较小的权重。
# 生成2维正态分布,生成的数据按分位数分为两类,500个样本,2个样本特征x1, y1 = make_gaussian_quantiles(n_samples=500, n_features=2,n_classes=2)# 生成2维正态分布,生成的数据按分位数分为两类,400个样本,2个样本特征均值都为3x2, y2 = make_gaussian_quantiles(mean=(3, 3), n_samples=500, n_features=2, n_classes=2)# 将两组数据合成一组数据x_data = np.concatenate((x1, x2))y_data = np.concatenate((y1, - y2 + 1))
![]() # 决策树模型model = tree.DecisionTreeClassifier(max_depth=3)# 输入数据建立模型model.fit(x_data, y_data)# 获取数据值所在的范围x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))z = model.predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据z = z.reshape(xx.shape)# 等高线图cs = plt.contourf(xx, yy, z)# 样本散点图plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)plt.show() ![]()
0.777
![]() # 模型准确率model.score(x_data,y_data)
![]() 0.976 总结一下,组合算法(combiner algorithm)使用所有其他算法的预测作为附加输入(additional inputs)来训练得到最终的预测结果。理论上可以表示任何一种组合学习方法(ensemble techniques);实际中,单层的逻辑回归模型(single-layer logistic regression model)通常被用作组合器(combiner)。 非监督学习 9. 降维—主成分分析 ![]()
# 载入数据data = np.genfromtxt('data.csv', delimiter=',')x_data = data[:,0]y_data = data[:,1]plt.scatter(x_data,y_data)plt.show()print(x_data.shape) ![]()
newData,meanVal=zeroMean(data) # np.cov用于求协方差矩阵,参数rowvar=0说明数据一行代表一个样本covMat = np.cov(newData, rowvar=0)
array([[ 94.99190951, 125.62024804], [125.62024804, 277.49520751]])
# 特征值eigVals
# 特征向量eigVects
# 对特征值从小到大排序eigValIndice = np.argsort(eigVals)eigValIndice
top = 1# 最大的n个特征值的下标n_eigValIndice = eigValIndice[-1:-(top+1):-1]
array([1], dtype=int64)
matrix([[-0.45402951], [-0.89098665]])
# 利用低纬度数据来重构数据reconMat = (lowDDataMat*n_eigVect.T) + meanValreconMat
![]() 10. 聚类分析续集等下篇文章! |
|