赞
踩
这几天再补吴恩达的作业,刚好以前的逻辑回归代码还没实现,这边就先贴上来。
作业中只给到5000个训练样本,且0的标签为10。代码中拿了4000个作为训练,1000个测试
import scipy.optimize as opt import scipy.io as scio import matplotlib.pyplot as plt import numpy as np '''*************************************************************** * @Fun_Name : def loadData(filename) * @Function : 从数据中分离特征和标签,加入每个样本的第一个特征1,并且将其打乱,前4000个样本做训练集,后1000个训练集 * @Parameter : 文件名 * @Return : 特征 (5000 ,400) 标签 (5000 ,1) array * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 10:10 2020-06-08***''' def loadData(filename , rand): mat = scio.loadmat(filename) #得到数据类型为字典 labels = mat['y'] #将header是y的放在数组中 features = mat['X'] #将header是X的放在数组中 m = features.shape[0] #得到样本数 column = np.ones(m) #得到(m,)都为1的列表 features = np.insert(features,0,values=column,axis=1) #插入到样本第一列 # 将数据打乱 4000个训练 1000个测试 np.random.seed(rand) #rand随机种子,当rand一致时,features和labels打乱顺序一致,保证一一对应 np.random.shuffle(features) #打乱 np.random.seed(rand) np.random.shuffle(labels) trainFeatures = features[0:4000,:] #取前4000个作为训练样本 testFeatures = features[4000:5000,:] #后1000个位测试样本 trainLabels = labels[0:4000] testLabels = labels[4000:5000] return trainFeatures ,testFeatures,trainLabels,testLabels '''*************************************************************** * @Fun_Name : def visualizing(features , labels): * @Function : 可视化,打乱后可用这个函数看看特征和标签是否对应 * @Parameter : * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 21:01 2020-06-08***''' def visualizing(features , labels): featuresShow = np.delete(features,0,axis=1) #要还原图象,要将特征中第一列添加的1舍去 m = featuresShow.shape[0] #得到样本个数 image = featuresShow.reshape(m,20,20) #将400->20,20维度 for i in range(910,920): #随便抽10张出来对比下看看是否对应 plt.imshow(image[i].T) #转置是为了原图是横着的,转置为了视觉效果更好 print(labels[i]) plt.show() '''*************************************************************** * @Fun_Name : def sigmoid(z): * @Function : 不做解释 * @Parameter : * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 21:10 2020-06-08***''' def sigmoid(z): return 1/(1 + np.exp(-z)) '''*************************************************************** * @Fun_Name : def dealLabels(labels,N): * @Function : 为一对多训练做准备 * @Parameter : labels 标签 ,N训练的数字 ,比如训练2,那就将标签=2改为1,区域标签改为0 * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 21:11 2020-06-08***''' def dealLabels(labels,N): deallabels = labels.copy() #深拷贝 one = np.nonzero(deallabels == N) #找到deallabels == N的索引 zero = np.nonzero(deallabels != N) #找到deallabels != N的索引 deallabels[one] = 1 #将deallabels == N的标签改为1 deallabels[zero] = 0 return deallabels '''*************************************************************** * @Fun_Name : def cost(theta , features , labels , lamda): * @Function : 计算损失函数 正则化 下面都是公式 * @Parameter : * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 21:14 2020-06-08***''' def cost(theta , features , labels , lamda): m , n = features.shape theta = theta.reshape(n,1) A = sigmoid(np.dot(features, theta)) cost1 = (- np.dot(labels,np.log(A)) - np.dot((1-labels),np.log(1-A)))/m cost2 = (lamda/(2*m))*np.dot(theta[1:n].T,theta[1:n]) return (float)(cost1 + cost2) '''*************************************************************** * @Fun_Name : def gradient(features , theta) * @Function : 求梯度 * @Parameter : feature [5000,401] theta [401,1] * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 11:29 2020-06-08***''' def gradient(theta , features , labels , lamda): m , n= features.shape theta = theta.reshape(n, 1) A = sigmoid(np.dot(features, theta)).reshape(m,1) gradient1 = np.dot(features.T,(A - labels.T))/m gradient2 = (lamda / m) * theta gradient2[0] = 0 return (gradient2 + gradient1) '''*************************************************************** * @Fun_Name : def onevsall(trainFeatures,trainLabels,lamda = 0.01): * @Function : 一对多训练 * @Parameter : lamda正则化参数 * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 21:19 2020-06-08***''' def onevsall(trainFeatures,trainLabels,lamda = 0.01): m, n = trainFeatures.shape theta = np.zeros(shape=[10, n]) #将theta变成10,n 每一行记录一个数字训练好的参数 #theta[0]记录的是数字1的训练参数,1是2,2是3,..9的话是0 for i in range(1,11): #改数据集中0的标签值为10 所以从1开始到10 deallabels = dealLabels(trainLabels, i).T # 1,4000 #看上面注解 theta[i-1] = opt.fmin_tnc(func=cost, x0=theta[i-1], fprime=gradient, args=(trainFeatures, deallabels, lamda))[0].reshape(1,n) #优化的梯度下降算法 print("第%d/10次训练成功*****************************************************"%(i)) return theta.T '''*************************************************************** * @Fun_Name : def predict(theta,testFeatures,testLabels): * @Function : 预测 * @Parameter : * @Return : * @Creed : Talk is cheap , show me the code ***********************xieqinyu creates in 21:22 2020-06-08***''' def predict(theta,testFeatures,testLabels): m = testFeatures.shape[0] accury = 0 Predict = np.dot(testFeatures,theta) #每一行是每个样本在1 2 3 4 5 6 7 8 9 10 的概率值 temp = Predict.argmax(axis=1) + 1 #求取每行的最大值的索引 加1是因为索引是0 1 2 3 4 5 6 7 8 9.0代表的是1 .......9代表十(实际上是0) for i in range(m): if temp[i] == testLabels[i]: accury += 1 print(float(accury/m)) trainFeatures ,testFeatures,trainLabels,testLabels = loadData("ex3data1.mat",100) predict(onevsall(trainFeatures,trainLabels,0.01),testFeatures,testLabels)
效果在正则化参数为0.01的情况下准确率在0.892,有时间可以画个lamda-cost图找最优的正则化参数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。