如何使用逻辑回归 (logistic regression)来解决多类别分类问题
第一个例子:假如说你现在需要一个学习算法能自动地将邮件归类到不同的文件夹里,或者说可以自动地加上标签,那么,你也许需要一些不同的文件夹,或者不同的标签来完成这件事,来区分开来自工作的邮件、来自朋友的邮件、来自家人的邮件或者是有关兴趣爱好的邮件,那么,我们就有了这样一个分类问题:其类别有四个,分别用y=1、y=2、y=3、y=4 来代表。
第二个例子是有关药物诊断的,如果一个病人因为鼻塞来到你的诊所,他可能并没有生病,用 这个类别来代表;或者患了感冒,用y=1,y=2,y=3 来代表;或者得了流感用来代表。
如果你正在做有关天气的机器学习分类问题,那么你可能想要区分哪些天是晴天、多云、雨天、或者下雪天,对上述所有的例子,y 可以取一个很小的数值,一个相对"谨慎"的数值,比如1 到3、1到4或者其它数值,以上说的都是多类分类问题,顺便一提的是,对于下标是0 1 2 3,还是 1 2 3 4 都不重要,我更喜欢将分类从 1 开始标而不是0,其实怎样标注都不会影响最后的结果
然而对于之前的一个,二元分类问题,我们的数据看起来可能是像这样:
对于一个多类分类问题,我们的数据集或许看起来像这样:
下面将介绍如何进行一对多的分类工作,有时这个方法也被称为"一对余"方法。
我们先从用三角形代表的类别1开始,实际上我们可以创建一个,新的"伪"训练集,类型2和类型3定为负类,类型1设定为正类,我们创建一个新的训练集,如下图所示的那样,我们要拟合出一个合适的分类器。
最后我们得到一系列的模型简记为:
最后,在我们需要做预测时,我们将所有的分类机都运行一遍,然后对每一个输入变量,都选择最高可能性的输出变量。
吴恩达多分类代码
实现手写数字(0到9)的识别。你需要扩展之前的逻辑回归,并将其应用于一对多的分类。
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
#这是一个MATLAB格式的.m文件,其中包含5000个20*20像素的手写字体图像,
# 以及他对应的数字。另外,数字0的y值,对应的是10
#用Python读取我们需要使用SciPy
from scipy.io import loadmat
from sklearn.metrics import classification_report #这个包是评价报告
data = loadmat('E:\machine studdy\Coursera-ML-AndrewNg-Notes-master\code\ex3-neural network\ex3data1.mat')
X=data['X']
print(X.shape)
y=data['y']
print(y.shape)
def plot_image(X):
number=np.random.randint(5000)
image=X[number,:]
fig,ax=plt.subplots(figsize=(1,1))
ax.imshow(image.reshape(20,20).T,cmap='gray_r')
plt.xticks([])
plt.yticks([])
def plot100_image(X):
samper_index=np.random.choice(len(X),100) #生成100个随机数字
images=X[samper_index,:]
fig,ax=plt.subplots(ncols=10,nrows=10,figsize=(8,8),sharex=True,sharey=True) #共享所有的格式
#ax.imshow(images.reshape(20, 20).T, cmap='gray_r')
for r in range(10):
for c in range(10):
ax[r,c].imshow(images[10*r+c].reshape(20,20).T,cmap='gray_r')
plt.xticks([])
plt.yticks([])
def sigmoid(z):
return 1/(1+np.exp(-z))
def costfunction(theta,X,y,learningRate):
theta=np.matrix(theta)
X=np.matrix(X)
y=np.matrix(y)
#这里出错了 导致X 和theta的乘法 对不上 艹
first=np.multiply(-y,np.log(sigmoid(X* theta.T)))
second=np.multiply((1-y),np.log(1-sigmoid(X* theta.T)))
reg=(learningRate/(2*len(X)))*np.sum(np.power(theta[:,1:theta.shape[1]],2))
return np.sum(first-second)/len(X)+reg
"""def cost(theta, X, y, learningRate):
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
first = np.multiply(-y, np.log(sigmoid(X * theta.T)))
second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))
reg = (learningRate / (2 * len(X))) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))
return np.sum(first - second) / len(X) + reg
"""
#向量化梯度
"""def gradient(theta,X,y,learningRate):
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
parameters =int(theta.ravel().shape[1])
error =sigmoid(theta.T *X)-y
#不清楚为什么加上 X.T 和 最后的转置T
grad=((X.T * error)/len(X)).T+((learningRate/len(X))*theta)
# grad=((X.T * error)/len(X)).T+((learningRate/len(X))*theta)
#因为第x0不需要正则化,所以更新第一个
grad[0, 0] = np.sum(np.multiply(error, X[:, 0])) / len(X)
#返回一维化
return np.array(grad).ravel()
"""
def gradient(theta, X, y, learningRate):
theta = np.matrix(theta)
X = np.matrix(X)
y = np.matrix(y)
parameters = int(theta.ravel().shape[1])
error = sigmoid(X * theta.T) - y
#1,401
grad = ((X.T * error) / len(X)).T + ((learningRate / len(X)) * theta)
# intercept gradient is not regularized
grad[0, 0] = np.sum(np.multiply(error, X[:, 0])) / len(X)
return np.array(grad).ravel()
#一对多分类器
from scipy.optimize import minimize
"""def one_vs_all(X, y, num_labels, learning_rate):
rows = X.shape[0]
params = X.shape[1]
# k * (n + 1) array for the parameters of each of the k classifiers
all_theta = np.zeros((num_labels, params + 1))
#增加一行新的常数项
X = np.insert(X, 0, values=np.ones(rows), axis=1)
for i in range(1,num_labels+1):
theta=np.zeros(params+1) #+1可能是为了增加一个theta0
#生成一个数组,目前不知道有什么用
y_i=np.array([1 if label==i else 0 for label in y])
#调整y的形状为rows行 1列
y_i=np.reshape(y_i,(rows,1))
fmin=minimize(fun=costfunction,x0=theta,args=(X,y_i,learning_rate),method='TNC', jac=gradient)
all_theta[i-1,:]=fmin.x
return all_theta"""
def one_vs_all(X, y, num_labels, learning_rate):
rows = X.shape[0]
params = X.shape[1]
# k * (n + 1) array for the parameters of each of the k classifiers
all_theta = np.zeros((num_labels, params + 1))
# insert a column of ones at the beginning for the intercept term
X = np.insert(X, 0, values=np.ones(rows), axis=1)
# labels are 1-indexed instead of 0-indexed
for i in range(1, num_labels + 1):
theta = np.zeros(params + 1) #1,401
y_i = np.array([1 if label == i else 0 for label in y])
#5000,1
y_i = np.reshape(y_i, (rows, 1))
# minimize the objective function
fmin = minimize(fun=costfunction, x0=theta, args=(X, y_i, learning_rate), method='TNC', jac=gradient)
all_theta[i - 1, :] = fmin.x
return all_theta
X=np.insert(X,0,1,1) #最后一个1指的是在哪个上面
rows = data['X'].shape[0]
params = data['X'].shape[1]
#所有的θ 10,401
alltheta=np.zeros([10,params+1])
X=np.insert(data['X'],0,values=np.ones(rows),axis=1)
#1,401
theta = np.zeros(params + 1)
y_0 = np.array([1 if label == 0 else 0 for label in data['y']])
y_0 = np.reshape(y_0, (rows, 1))
#计算能力不太够啊
all_theta = one_vs_all(data['X'], data['y'], 10, 1)
print(all_theta.shape)
def perdict_all(X,all_theta):
rows=X.shape[0]
params=X.shape[1]
num_labels=all_theta.shape[0]
# same as before, insert ones to match the shape
X = np.insert(X, 0, values=np.ones(rows), axis=1)
# convert to matrices
X = np.matrix(X)
all_theta = np.matrix(all_theta)
#预测概率,为什么,?
h=sigmoid(X* all_theta.T)
# create array of the index with the maximum probability
#numpy.argmax(array, axis) 用于返回一个numpy数组中最大值的索引值
#计算权重最大的一组判断是不是该数字
h_argmax = np.argmax(h, axis=1)
# because our array was zero-indexed we need to add one for the true label prediction
h_argmax = h_argmax + 1
return h_argmax
y_pred = perdict_all(data['X'], all_theta)
aoc=np.mean(y_pred==y)
print(aoc)