1 Logistic 多分类问题
面对Logistic多分类问题,通常的分类是将一类单独拎出来,然后其他剩下的分为另一类。这样就可以利用二元Logistic回归的思路了。
比如下图,我们一共有三个类,那么我们会有三个分类器,然后依此计算hypothesis函数的值,最后看那个类别下的h值最大,那么就将其归为这一类。
2 过拟合问题
简单来说,过拟合就是指一个模型在训练集上表现的相当好(代价函数可能非常的接近于0 ),但是在测试集上的表现比较差,无法准确的进行预测。
下图中,图1:可见一元的线性方程无法较好的去拟合这个房价的模型(因为,房价在随着大小的增加越来越趋向于稳定,但是这个模型拟合的线是没有表现出来稳定的趋势的。),因此我们可以叫这种现象为“欠拟合(Under fitting)”或“高偏差(High bias)”; 图3 可以看到是一个高阶的模型,它拟合出来的线是由很多上下波动的,这可以叫“过度拟合(Over fitting)”或“高方程”.
解决:
- 减少特征数量
- 正则化
概念:
通过惩罚模型中参数的方法来,使得模型变的平滑。
看下图的这个例子。
原来的模型当中theta_3,theta_4分别是x的三次和x的四次的参数。因为高阶的存在,会使得我们的模型变得弯弯扭扭。那么我们如果希望这个模型和左边的那个相似应该怎么做呢?
那必然是要减少theta_3和theta_4对于模型的影响!减少到theta_3和theta_4几乎等于0(就好像被这两项被去掉了一样,这样我们就可以得到一个近似左图的模型了。)
那么怎么做呢?
我们可以在后面添加两项,如下图。
因为我们期望这个代价函数得到最小值,那么我们肯定不希望前面系数为1000的theta_3和theta_4大,而是要这两个参数尽可能的小,从而我们的theta_3,和theta_4对于整个模型的影响就会减小,使我们得到一个比较平滑模型。
上面的例子当中,我们知道想要惩罚哪一项,但是当我们的特征数量非常多的时候,我们往往无法知道我们需要惩罚哪些特征项。
因此,利用正则化来缩小出来theta_0外的所有的参数
这里的lambda就是正则化参数,它是用来控制两个目标的取舍的。
第一个目标:更好的拟合数据
第二个目标:使得参数尽可能的小
注:当lambda过大,可能就会对所有的参数惩罚过大,最后就的h函数可能就成为下面这样了。。
3 线性回归正则化
- 梯度下降法:
我们将上面讨论到的正则化方法加入到梯度下降函数当中,那么我们求偏导之后的结果就如下图所示。
其中alpha*(lamda/m)是一个很小很小的正数,所以说,每次更新一次参数,那么我们的theta就会是原来的theta*比一小一点点的数,再减去后面的那项。
- 正规方程法:
在原来的基础上增加一个lambda*一个对角矩阵(假设矩阵为A,那么A11就是0,对角线其他值都为1)
对于不可逆问题:
利用正则化,只要保证lambda>0,那么就可以使得矩阵可逆。
4 Logistic 回归正则化
- 损失函数
- 梯度下降
5 Logistic回归正则化代码实例
- 首先读取数据,查看数据分布情况
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
Data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
Data.head(30)
sns.set(context='notebook',style='ticks',font_scale = 1.5)
sns.lmplot('exam1','exam2',hue = 'accepted',data=Data,height = 6,fit_reg=False,scatter_kws={'s':50})
plt.title('Regularized Logistic Regression')
plt.show()
结果如下:
从散点分布情况来看,这个条决策线应当是一个近似圆形的线才能分割。
- 因为目前读取的数据最高只有一次项,所以要写一个函数来进行转化数据。
def feature_mapping(x,y,power,as_ndarray=False):
"""将函数转化为高阶,把两个特征值转化为多个特征值
polynomial expansion法"""
data = {'f{}{}'.format(i-p,p) : np.power(x,i-p)*np.power(y,p)
for i in np.arange(power+1)
for p in np.arange(i+1)}
if as_ndarray:
return np.array(pd.DataFrame(data))
else:
return pd.DataFrame(data)
x1 = np.array(Data['exam1'])
x2= np.array(Data['exam2'])
data = feature_mapping(x1,x2,power=6)
print(data.shape)
data.head()
注意根据两个数值可以看出是几次方:
f00:x10 * x20
f10: x11 * x20
f20: x12 * x20
所以根据输入power值多少,就可以计算到几次方,这样就可以应用到我们的正则化当中的。
- 定义必要的函数:
def get_y(Data):
return np.array(Data.iloc[:,-1])
def sigmoid(z):
return 1/(1+np.exp(-z))
def gradient(theta,x,y):
return (1/len(x))* x.T@ (sigmoid(x@theta)-y)
def cost(theta, X, y):
return np.mean(-y * np.log(sigmoid(X @ theta)) - (1 - y) * np.log(1 - sigmoid(X @ theta)))
def regcost(theta,x,y,l=1):
m = len(x)
theta_j1_jn = theta[1:] #首先新建一个theta函数,因为theta0不需要处理,所以取出theta1到n即可
regularized_term = (l/(2*m))* np.power(theta_j1_jn,2).sum() #根据公式计算出正则化项
return cost(theta,x,y)+regularized_term
def reg_descent(theta,x,y,l=1):
theta_j1_jn = theta[1:]
regularized_theta = (l/len(x))*theta_j1_jn #正则化项
regularized_term = np.concatenate([np.array([0]),regularized_theta]) #因为theta_0不动,这时候要将其组合回去
return gradient(theta,x,y) + regularized_term
- 利用scipy.optimize的minimize来进行拟合
import scipy.optimize as ops
theta = np.zeros(data.shape[1])
X = feature_mapping(x1,x2,power=6,as_ndarray=True)
y = get_y(Data)
res = ops.minimize(fun = regcost,x0 = theta,args=(X,y),method='Newton-CG',jac=reg_descent)
res
结果如下:
- 测试精确度
X = feature_mapping(x1,x2,power=6,as_ndarray=True)
y = get_y(Data)
res = ops.minimize(fun = regcost,x0 = theta,args=(X,y),method='Newton-CG',jac=reg_descent)
def pred_y(final_theta,x):
prob = sigmoid(x@final_theta)
test = []
for each in prob:
if each>0.5:
test.append(1)
else:
test.append(0)
return test
final_theta = res.x
pred = pred_y(final_theta,X)
print(classification_report(y,pred))
结果如下:
- 绘制决策边界:
def feature_mapped_logistic_regression(power,l):
"""获取最优拟合参数
Params:
power:函数最高次方
l:lambda
return:
final_theta:最优拟合参数"""
Data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
x0 = np.array(Data['exam1'])
x1 = np.array(Data['exam2'])
y = get_y(Data)
X = feature_mapping(x0,x1,power,as_ndarray=True) #获取高次方函数
theta = np.zeros(X.shape[1])
res = ops.minimize(fun=regcost,x0=theta,args=(X,y,l),method='TNC',jac=reg_descent)
final_theta = res.x
return final_theta
def find_decision_boundary(density, power, theta, threshhold):
""""找到最合适的参数
目前理解的不太清楚,希望知道的朋友可以留言告诉我一下,谢谢!"""
t1 = np.linspace(-1, 1.5, density) #因为我数据点都是分布在-1,1.5之间的,所以我取-1,1.5的等差数列密度为1000个,为了可以布满整个图像
t2 = np.linspace(-1, 1.5, density)
cordinates = [(x, y) for x in t1 for y in t2] #取得各个点的坐标
x_cord, y_cord = zip(*cordinates) #解压
mapped_cord = feature_mapping(x_cord, y_cord, power) # 进行高次运算
inner_product = np.array(mapped_cord) @ theta
decision = mapped_cord[np.abs(inner_product) < threshhold] #增加条件
return decision.f10, decision.f01 #获取x^1和y^1 用来画边界函数
def draw_boundury(power,l):
density =1000
threshhold= 2* 10**-3
final_theta = feature_mapped_logistic_regression(power,l)
x,y = find_decision_boundary(density, power, final_theta, threshhold)
dt = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
sns.lmplot('exam1','exam2',hue = 'accepted',data=dt,height=6,fit_reg=False,scatter_kws={'s':50})
plt.scatter(x,y,color='red',s=10)
plt.title('Desicion Boundary')
plt.show()
draw_boundury(power=6,l=1)
draw_boundury(power=6,l=0) #过拟合
draw_boundury(power=6,l=50) #欠拟合
结果:
lambda=1比较合适