文章原创,最近更新:2018-05-25
课程内容:Python实现逻辑回归与梯度下降策略
课程来源: python数据分析与机器学习实战-唐宇迪
我们将建立一个逻辑回归模型来预测一个学生是否被大学录取。假设你是一个大学系的管理员,你想根据两次考试的结果来决定每个申请人的录取机会。你有以前的申请人的历史数据,你可以用它作为逻辑回归的训练集。对于每一个培训例子,你有两个考试的申请人的分数和录取决定。为了做到这一点,我们将建立一个分类模型,根据考试成绩估计入学概率。
首先读取这个文件"LogiReg_data.txt"的数据前5行,看一下数据是长什么样子的,具体代码如下:(备注:Admitted是代表是否录取的意思)
import pandas as pd
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
print(pdData.head())
输出结果如下:
Exam 1 Exam 2 Admitted
0 34.623660 78.024693 0
1 30.286711 43.894998 0
2 35.847409 72.902198 0
3 60.182599 86.308552 1
4 79.032736 75.344376 1
对数据有个大致的了解之后,求出这个数据的维度,如下:
import pandas as pd
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
print(pdData.shape)
输出结果如下:
(100, 3)
分别用0,1表示正例和负例.'Exam 1'以及'Exam 2'分别录取的人数的散点图
案例代码如下:
import pandas as pd
import matplotlib.pyplot as plt
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
pdData.head()
print(pdData.shape)
positive=pdData[pdData["Admitted"]==1]
negative=pdData[pdData["Admitted"]==0]
fig, ax = plt.subplots(figsize=(10,5))
ax.scatter(positive['Exam 1'], positive['Exam 2'], s=30, c='b', marker='o', label='Admitted')
ax.scatter(negative['Exam 1'], negative['Exam 2'], s=30, c='r', marker='x', label='Not Admitted')
ax.legend()
ax.set_xlabel('Exam 1 Score')
ax.set_ylabel('Exam 2 Score')
输出结果如下:
蓝色的点代表是录取的,未被录取的是红色的.对两种颜色的点是否可以进画一条决策边界呢?
数据现在也有了,算法之前也推倒过了,怎么用python将逻辑回归实现出来?
首先要了解一下逻辑回归:
目标:建立分类器(求解出三个参数 θ0、θ1、θ2 )
备注:θ1对应'Exam 1'成绩,θ2对应'Exam 2'
设定阈值,根据阈值判断录取结果
备注:阈值指的是最终得到的概率值.将概率值转化成一个类别.一般是>0.5是被录取了,<0.5未被录取.
要完成的模块:
- sigmoid : 映射到概率的函数
- model : 返回预测结果值
- cost : 根据参数计算损失
- gradient : 计算每个参数的梯度方向
- descent : 进行参数更新
- accuracy: 计算精度
sigmoid 函数:
g:ℝ→[0,1] (值域是0到1)
g(0)=0.5 (当x=0时,y=0.5)
g(−∞)=0 (当x趋于负无穷时,y=0)
g(+∞)=1 (当x趋于正无穷时,y=1)
如果不知道sigmoid 函数长什么样子,可以看看如下的案例代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def sigmoid(z):
return 1/(1+np.exp(-z))
nums=np.arange(-10,10,step=1)
fig,ax=plt.subplots(figsize=(12,4))
ax.plot(nums,sigmoid(nums),"r")
输出结果如下:
当构造一个回归模型的时候,要把数据当中插入一列,让那一列的值都等于1.要把数值计算转化成矩阵的运算.根据理论让代码实现出来,
备注:
-
知识点1:
np.dot()这个是矩阵的乘法,然后将数据传入到sigmoid(z),相当于以下截图的过程.
- 知识点2:
pdData.insert(0, 'Ones', 1)
具体用法如下:
numpy.insert(arr,obj,value,axis=None)
arr:为插入目标列的位置
obj:插入为目标列的名称
value:为想要插入列的数值
axis:为插入的维度
例如:
import pandas as pd
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
pdData.insert(0, 'Ones', 1)
print(pdData.head())
输出结果如下:
One Exam 1 Exam 2 Admitted
0 1 34.623660 78.024693 0
1 1 30.286711 43.894998 0
2 1 35.847409 72.902198 0
3 1 60.182599 86.308552 1
4 1 79.032736 75.344376 1
- 知识点3:
pd.as_matrix()将frame转换为其Numpy数组表示。
建立一个4*2的矩阵,利用shape可输出矩阵的维度,即行数和列数。shape[0]和shape[1]分别代表多少行?和多少列?结果如图.
- 知识点4:
theta是当前的一个参数,虽然参数没有一个具体的值,但是也需要给参数进行占位.通常情况下,指定一个结构的时候,虽然里面的值我们不关心,但是必须有这样的位置给它创建出来.通常情况下用0进行填充,比如这里用到了theta=np.zeros([1,3]),创建了1行3列填充数据为0的矩阵.相当于构造了3个θ0、θ1、θ2参数.
构造完之后,不知道准不准?那应该怎么办呢?
首先查看x前5行对应的值是对的?
import numpy as np
import pandas as pd
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
pdData.insert(0, 'Ones', 1)
orig_data=pdData.as_matrix()
cols=orig_data.shape[1]
x=orig_data[:,0:cols-1]#1-倒数第1列的数据
y=orig_data[:,cols-1:cols]#倒数第1列的数据
theta=np.zeros([1,3])#1行三列的矩阵全部填充为0
print(x[:5])
输出结果如下:
[[ 1. 34.62365962 78.02469282]
[ 1. 30.28671077 43.89499752]
[ 1. 35.84740877 72.90219803]
[ 1. 60.18259939 86.3085521 ]
[ 1. 79.03273605 75.34437644]]
输出的结果是与截图相一致的
再看看y的前5列是否有问题?
import numpy as np
import pandas as pd
pdData.insert(0, 'Ones', 1)
orig_data=pdData.as_matrix()
cols=orig_data.shape[1]
x=orig_data[:,0:cols-1]#1-倒数第1列的数据
y=orig_data[:,cols-1:cols]#倒数第1列的数据
theta=np.zeros([1,3])#1行三列的矩阵全部填充为0
print(y[:5])
输出结果如下:
[[ 0.]
[ 0.]
[ 0.]
[ 1.]
[ 1.]]
从输出的结果来看是没有问题的.
在看看theta是否有问题?
pdData.insert(0, 'Ones', 1)
orig_data=pdData.as_matrix()
cols=orig_data.shape[1]
x=orig_data[:,0:cols-1]#1-倒数第1列的数据
y=orig_data[:,cols-1:cols]#倒数第1列的数据
theta=np.zeros([1,3])#1行三列的矩阵全部填充为0
print(theta)
输出结果如下:
[[ 0. 0. 0.]]
检查完之后,在分别打印x.shape,y.shape,theta.shape的维度
pdData.insert(0, 'Ones', 1)
orig_data=pdData.as_matrix()
cols=orig_data.shape[1]
x=orig_data[:,0:cols-1]#1-倒数第1列的数据
y=orig_data[:,cols-1:cols]#倒数第1列的数据
theta=np.zeros([1,3])#1行三列的矩阵全部填充为0
print(x.shape,y.shape,theta.shape)
输出结果如下:
(100, 3) (100, 1) (1, 3)
从输出的结果来看,这三个矩阵的维度也是没有任何问题的.
接下来对数据进行组合,并得到最终的结果.
首先先定义损失函数:
将对数似然函数去负号
求平均损失
这个损失函数是怎么来的,是根据以下截图的应用梯度上升最大值得来的:(-1/n的过程分步骤,先对数似然函数去负号,再除以1/n)
这个函数用python代码怎么表达cost()这个损失函数呢?并计算这个损失函数?
import numpy as np
import pandas as pd
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
def sigmoid(z):
return 1/(1+np.exp(-z))
def model(X,theta):
return sigmoid(np.dot(X,theta.T))
def cost(x,y,theta):
left=np.multiply(-y,np.log(model(x,theta)))
right=np.multiply(1-y,np.log(1-model(x,theta)))
return np.sum(left-right)/(len(x))
pdData.insert(0, 'Ones', 1)
orig_data=pdData.as_matrix()
cols=orig_data.shape[1]
x=orig_data[:,0:cols-1]#1-倒数第1列的数据
y=orig_data[:,cols-1:cols]#倒数第1列的数据
theta=np.zeros([1,3])#1行三列的矩阵全部填充为0
print(cost(x,y,theta))
输出结果如下:
0.69314718056
接下来,怎么计算梯度函数?
梯度函数是以下截图
就是求偏导,求导的过程就是以下截图的内容
构造theta参数的时候,构造的是3个参数θ0、θ1、θ2参数,算出来的梯度算几个呀?构造的时候构造了3个θ0、θ1、θ2参数,那这三个参数求解的时候,应该求出几个梯度呀?显然也是三个.具体相关知识点如下:
1)在python代码中,定义grad为梯度,用np.zeros(theta.shape)中的zeros函数进行占位.梯度应与theta.shape的维度是一致的.
2)这里的error=yi−hθ(xi),跟表达式有点相反了,原因是把负号提到里面去了.
3)np.ravel()将多维数组降为一维,返回的是视图,修改时会影响原始矩阵 .
案例代码如下:
import numpy as np
a = np.array([[1 , 2] , [3 , 4]])
c=a.ravel()
print(c)
c[0]=10
print(c)
输出结果如下:
[1 2 3 4]
[10 2 3 4]
梯度函数怎么用python表达呢?
def gradient(x, y, theta):
grad = np.zeros(theta.shape)
error = (model(x, theta)- y).ravel()
for j in range(len(theta.ravel())): #for each parmeter
term = np.multiply(error, x[:,j])
grad[0, j] = np.sum(term) / len(x)
return grad
比较3种不同梯度下降的方法,具体梯度下降的方法如下截图:
- 第一种策略
是按照迭代次数进行停止,因为进行模型优化的时候,可以进行迭代,在不断进行迭代的过程中,无论是多少次,最终都需要停下来.这里就设置了3种停止的策略.
比如设置迭代次数是2000次,一旦达到次数,每次进行优化,每次进行参数更新,就进行计数.迭代次数跟什么挂钩呢?就是更新一次参数就是完成了一次迭代.再更新一次参数,就是再完成了一次迭代.根据迭代次数,指定成一个值,达到了这样的一个值,就完成了更新.
- 第二种策略
是看一下损失函数的目标函数的变化,在迭代的过程中,可以知道迭代之前的目标函数,迭代完之后的目标函数,如果这两个目标函数差异非常小,几乎没有变化,迭代就可以停止下来.
- 第三种策略
根据梯度,如果前后两次迭代梯度的值差不多,几乎没啥变化,那么迭代也是可以停止下来的.
以上就是三种不同的梯度下降方法,不同的方法进行比较,看一下这三种算法得到的结果怎么样?不仅要看这三种停止策略,还要结合不同梯度下降,比如小批量的梯度下降/随机梯度下降/批量梯度下降.
首先定义一个函数,针对不同的三种停止策略,具体如下:
STOP_ITER = 0
STOP_COST = 1
STOP_GRAD = 2
def stopCriterion(type, value, threshold):
#设定三种不同的停止策略
if type == STOP_ITER: return value > threshold
elif type == STOP_COST: return abs(value[-1]-value[-2]) < threshold
elif type == STOP_GRAD: return np.linalg.norm(value) < threshold
在做迭代更新的时候,首先对数据进行洗牌,洗牌是因为现在的数据看起来是有规律的,因为数据是我们自己进行收集的,收集的过程中可能按照某种顺序.比如身高排序,比如先收集男生的再收集女生的.
为了使模型的泛化能力更强,第一步先把数据进行打乱,做一个乱序的数据,通常把这种做法叫做洗牌,也叫shuffle操作,numpy有提供这样的操作.
通过numpy中的random模块,也就是随机模块,有shuffle函数,将数据传进去就可以进行洗牌.洗牌之后,把数据重新的指定好,然后再重新指定对应的x,y.
import numpy.random
#洗牌
def shuffleData(data):
np.random.shuffle(data)
cols = data.shape[1]
x = data[:, 0:cols-1]
y = data[:, cols-1:]
return x, y
之前有说过,不同梯度下降,所消耗的时间也是不一样的.这里还要看一下时间对结果的影响.这里通过定义descent函数进行.
- data这里指的是数据;theta这里指的是参数;batchSize指定成1,那就是随机梯度下降,指定成总的样本数,那就是批量梯度下降,指定正1到总体之间,那就是小批量梯度下降;thresh指的是策略对应的阈值;alpha指的是学习率.
- 首先初始化值,i = 0第一次迭代,k = 0第0次batch. x, y = shuffleData(data)对xy进行洗牌.
- grad = gradient(x[k:k+batchSize], y[k:k+batchSize], theta)因为有三种不同的梯度下降的方法,每种方法对应数据的个数是不一样的.这里按实际传进来的数据进行计算.
- theta = theta - alpha*grad参数更新的过程.
- costs.append(cost(x, y, theta))将每一次迭代的损失都画出来.
- 按什么样的方式进行停止策略.如果到了停止的策略,则就跳出循环,直接返回一个新的结果值,就可以了.
import time
def descent(data, theta, batchSize, stopType, thresh, alpha):
#梯度下降求解
init_time = time.time()
i = 0 # 迭代次数
k = 0 # batch
x, y = shuffleData(data)
grad = np.zeros(theta.shape) # 计算的梯度
costs = [cost(x, y, theta)] # 损失值
while True:
grad = gradient(x[k:k+batchSize], y[k:k+batchSize], theta)
k += batchSize #取batch数量个数据
if k >= n:
k = 0
x, y = shuffleData(data) #重新洗牌
theta = theta - alpha*grad # 参数更新
costs.append(cost(x, y, theta)) # 计算新的损失
i += 1
if stopType == STOP_ITER: value = i
elif stopType == STOP_COST: value = costs
elif stopType == STOP_GRAD: value = grad
if stopCriterion(stopType, value, thresh): break
return theta, i-1, costs, grad, time.time() - init_time
为了使画图的时候知道当前迭代多少次,以及停止策略以及batch的一个结果,就定义了一个功能性的一个函数runExpe().
-
theta, iter, costs, grad, dur = descent(data, theta, batchSize, stopType, thresh, alpha)先对一个值进行初始化,然后进行求解.这是核心代码.
-
就是选择梯度下降的方式以及停止策略
这一部分是怎么在图上显示它的名字.是根据传进来的参数,比如是批量梯度下降or随机梯度下降or小批量梯度下降的参数.以下代码时初始化,根据选择传进来的参数,如果数据传进来一个,则是随机梯度下降方式,如果传进来的是总体则是批量梯度下降;如果传进来的是小批量的数据则是小批量梯度下降.
name = "Original" if (data[:,1]>2).sum() > 1 else "Scaled"
name += " data - learning rate: {} - ".format(alpha)
if batchSize==n: strDescType = "Gradient"
elif batchSize==1: strDescType = "Stochastic"
else: strDescType = "Mini-batch ({})".format(batchSize)
name += strDescType + " descent - Stop: "
if stopType == STOP_ITER: strStop = "{} iterations".format(thresh)
elif stopType == STOP_COST: strStop = "costs change < {}".format(thresh)
else: strStop = "gradient norm < {}".format(thresh)
name += strStop
- 然后下面代码就是画图以及展示得到的一个结果
fig, ax = plt.subplots(figsize=(12,4))
ax.plot(np.arange(len(costs)), costs, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title(name.upper() + ' - Error vs. Iteration')
- 完整的runExpe函数定义代码如下:
def runExpe(data, theta, batchSize, stopType, thresh, alpha):
#import pdb; pdb.set_trace();
theta, iter, costs, grad, dur = descent(data, theta, batchSize, stopType, thresh, alpha)
name = "Original" if (data[:,1]>2).sum() > 1 else "Scaled"
name += " data - learning rate: {} - ".format(alpha)
if batchSize==n: strDescType = "Gradient"
elif batchSize==1: strDescType = "Stochastic"
else: strDescType = "Mini-batch ({})".format(batchSize)
name += strDescType + " descent - Stop: "
if stopType == STOP_ITER: strStop = "{} iterations".format(thresh)
elif stopType == STOP_COST: strStop = "costs change < {}".format(thresh)
else: strStop = "gradient norm < {}".format(thresh)
name += strStop
print ("***{}\nTheta: {} - Iter: {} - Last cost: {:03.2f} - Duration: {:03.2f}s".format(
name, theta, iter, costs[-1], dur))
fig, ax = plt.subplots(figsize=(12,4))
ax.plot(np.arange(len(costs)), costs, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title(name.upper() + ' - Error vs. Iteration')
return theta
当n值指定为100的时候,相当于整体对于梯度下降,为什么呢?因为我的数据样本就100个.
传进来的数据是按照迭代次数进行停止的,指定迭代次数的参数是thresh=5000.学习率是alpha=0.000001.
n=100
runExpe(orig_data, theta, n, STOP_ITER, thresh=5000, alpha=0.000001)
以下是正常模型收敛的一个图的样子:
x轴是我的迭代次数,y轴是我的目标函数,随着迭代,目标函数进行一个收敛.5000次之后最终得到一个结果.共用了0.18s,完成了一个整体的迭代,速度还是比较快的,因为数据量比较小.
完整的代码如下:
import numpy as np
import pandas as pd
import time
import matplotlib.pyplot as plt
pdData=pd.read_csv("LogiReg_data.txt",header=None,names=['Exam 1', 'Exam 2', 'Admitted'])
def sigmoid(z):
return 1/(1+np.exp(-z))
def model(x,theta):
return sigmoid(np.dot(x,theta.T))
def cost(x,y,theta):
left=np.multiply(-y,np.log(model(x,theta)))
right=np.multiply(1-y,np.log(1-model(x,theta)))
return np.sum(left-right)/(len(x))
def gradient(x,y,theta):
grad=np.zeros(theta.shape)
error=(model(x,theta)-y).ravel()
for j in range(len(theta.ravel())):
term=np.multiply(error,x[:,j])
grad[0,j]=np.sum(term)/len(x)
return grad[0,j]
STOP_ITER = 0
STOP_COST = 1
STOP_GRAD = 2
def stopCriterion(type, value, threshold):
#设定三种不同的停止策略
if type == STOP_ITER: return value > threshold
elif type == STOP_COST: return abs(value[-1]-value[-2]) < threshold
elif type == STOP_GRAD: return np.linalg.norm(value) < threshold
def shuffleData(data):
np.random.shuffle(data)
cols = data.shape[1]
x = data[:, 0:cols-1]
y = data[:, cols-1:]
return x, y
def descent(data, theta, batchSize, stopType, thresh, alpha):
#梯度下降求解
init_time = time.time()
i = 0 # 迭代次数
k = 0 # batch
x, y = shuffleData(data)
grad = np.zeros(theta.shape) # 计算的梯度
costs = [cost(x, y, theta)] # 损失值
while True:
grad = gradient(x[k:k+batchSize], y[k:k+batchSize], theta)
k += batchSize #取batch数量个数据
if k >= n:
k = 0
x, y = shuffleData(data) #重新洗牌
theta = theta - alpha*grad # 参数更新
costs.append(cost(x, y, theta)) # 计算新的损失
i += 1
if stopType == STOP_ITER: value = i
elif stopType == STOP_COST: value = costs
elif stopType == STOP_GRAD: value = grad
if stopCriterion(stopType, value, thresh): break
return theta, i-1, costs, grad, time.time() - init_time
def runExpe(data, theta, batchSize, stopType, thresh, alpha):
#import pdb; pdb.set_trace();
theta, iter, costs, grad, dur = descent(data, theta, batchSize, stopType, thresh, alpha)
name = "Original" if (data[:,1]>2).sum() > 1 else "Scaled"
name += " data - learning rate: {} - ".format(alpha)
if batchSize==n: strDescType = "Gradient"
elif batchSize==1: strDescType = "Stochastic"
else: strDescType = "Mini-batch ({})".format(batchSize)
name += strDescType + " descent - Stop: "
if stopType == STOP_ITER: strStop = "{} iterations".format(thresh)
elif stopType == STOP_COST: strStop = "costs change < {}".format(thresh)
else: strStop = "gradient norm < {}".format(thresh)
name += strStop
print ("***{}\nTheta: {} - Iter: {} - Last cost: {:03.2f} - Duration: {:03.2f}s".format(
name, theta, iter, costs[-1], dur))
fig, ax = plt.subplots(figsize=(12,4))
ax.plot(np.arange(len(costs)), costs, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title(name.upper() + ' - Error vs. Iteration')
return theta
pdData.insert(0, 'Ones', 1)
orig_data=pdData.as_matrix()
cols=orig_data.shape[1]
x=orig_data[:,0:cols-1]#1-倒数第1列的数据
y=orig_data[:,cols-1:cols]#倒数第1列的数据
theta=np.zeros([1,3])#1行三列的矩阵全部填充为0
n=100
runExpe(orig_data, theta, n, STOP_ITER, thresh=5000, alpha=0.000001)
停止策略
1)设定迭代次数停止策略:设定迭代次数
如果不认为的指定迭代次数,经过多少次的迭代可以达到阈值.
将
n=100
runExpe(orig_data, theta, n, STOP_ITER, thresh=5000, alpha=0.000001)
更改为
n=100
runExpe(orig_data, theta, n, STOP_ITER, thresh=0.0000001, alpha=0.001)
输出结果为
之前是迭代次数达到5000次接近0.63,现在的迭代次数达到了11万次接近0.37.只要改变迭代策略的时候,相当于不手动改变迭代次数,而是通过计算机自己计算,能够满足要求就自动停止下来,而自动停止共花了24.47s.
2)根据损失值停止策略:设定阈值 1E-6, 差不多需要110 000次迭代
当梯度值<阈值的时候,进行停止.同样的实验,可以得到我们当前的结果.
runExpe(orig_data, theta, n, STOP_COST, thresh=0.000001, alpha=0.001)
3)根据梯度变化停止:设定阈值 0.05,差不多需要40 000次迭代
runExpe(orig_data, theta, n, STOP_GRAD, thresh=0.05, alpha=0.001)
对比不同的梯度下降方法
1)随机梯度下降
这里的1是当前只迭代一个样本.损失值上上下下,跳转非常厉害.这样的问题应该怎么进行一个改变呢?迭代5000次的效果并不怎么好,但是时间非常快.
runExpe(orig_data, theta, 1, STOP_ITER, thresh=5000, alpha=0.001)
有点爆炸。。。很不稳定,再来试试把学习率调小一些..
runExpe(orig_data, theta, 1, STOP_ITER, thresh=15000, alpha=0.000002)
从输出的结果来看已经接近于收敛状态了.收敛效果比较低是接近于0.63,因此收敛结果也不是很满意.
速度快,但稳定性差,需要很小的学习率
2)小批量梯度下降
原来样本是100,现在改成16.
runExpe(orig_data, theta, 16, STOP_ITER, thresh=15000, alpha=0.001)
学习率比较小,但是也有一些问题,浮动也很大,这个问题应该怎么解决呢?不再把学习率调小一些,而是换一种方案.
浮动仍然比较大,我们来尝试下对数据进行标准化 将数据按其属性(按列进行)减去其均值,然后除以其方差。最后得到的结果是,对每个属性/每列来说所有数据都聚集在0附近,方差值为1.(备注:数据标准化,后面有专题)
from sklearn import preprocessing as pp
scaled_data = orig_data.copy()
scaled_data[:, 1:3] = pp.scale(orig_data[:, 1:3])
n=100
runExpe(scaled_data, theta, n, STOP_ITER, thresh=5000, alpha=0.001)
从输出结果来看,它好多了!原始数据,只能达到达到0.61,而我们得到了0.38个在这里! 所以对数据做预处理是非常重要的.
runExpe(scaled_data, theta, n, STOP_GRAD, thresh=0.02, alpha=0.001)
更多的迭代次数会使得损失下降的更多!
theta = runExpe(scaled_data, theta, 1, STOP_GRAD, thresh=0.002/5, alpha=0.001)
随机梯度下降更快,但是我们需要迭代的次数也需要更多,所以还是用batch的比较合适!!!
runExpe(scaled_data, theta, 16, STOP_GRAD, thresh=0.002*2, alpha=0.001)
对于概率值想得到一个类别值,那怎么样把概率值转换成类别值呢?
比如>0.5认为是≤0.5认为是0,这个概率值是可以自己自定义.
比如这里>0.5认为可以被录取,≤0.5认为这个人不能被录取.
def predict(X, theta):
return [1 if x >= 0.5 else 0 for x in model(X, theta)]
阈值设置之后,就要设置精度,在当前数据当中,认为是自己对了多少个?错了多少个?100个数据当中,一共对了89个,最终的结果是等于89%.通过梯度下降,梯度回归,最终算出精度是等于89%.
scaled_X = scaled_data[:, :3]
y = scaled_data[:, 3]
predictions = predict(scaled_X, theta)
correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y)]
accuracy = (sum(map(int, correct)) % len(correct))
print ('accuracy = {0}%'.format(accuracy))
网友评论