本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
代码:
iris=pd.read_csv(r'Desktop\iris.csv',sep=',',delimiter=',')
dummy=pd.get_dummies(iris['Species'])#通过哑变量类别数据化
iris = pd.concat([iris, dummy], axis =1 )
del iris['Unnamed: 0']
iris = iris.loc[0:99, :]
#定义回归函数,即sigmoid函数
def logit(x):
return 1./(1+np.exp(-x))
temp = pd.DataFrame(iris['Sepal.Length'])
#添加“1”列到temp
temp['x0'] = 1.#加一列创建计算矩阵
##整理出X矩阵 和 Y矩阵
X=temp.reindex(columns=['x0','Sepal.Length'])
Y = iris['setosa'].values
#两种算法的实现
#批量梯度下降法
def logitic_fuc(X,Y,alpha=0.0065,iteration_1=3000):
m,n = X.shape #矩阵大小
#alpha = 0.0065 #设定学习速率
theta_g = np.zeros(n) #初始化参数
#iteration_1=3000
J = pd.Series(np.zeros(iteration_1, dtype = float)) #构造损失函数承载器
for i in range(iteration_1):
h = logit(np.dot(X, theta_g)) #回归函数
J[i] = -(1/100.)np.sum(Ynp.log(h)+(1-Y)*np.log(1-h)) #计算损失函数值
diff = h - Y #概率差
grad = np.dot(X.T, diff) #梯度,
theta_g -= alpha * grad#调节学习速率,会得到不同曲线
J.plot()
plt.show()
return logit(np.dot(X, theta_g))
logitic_fuc(X,Y,alpha=0.0000000000005,iteration_1=5000)
C:\Users\dongfeng\Anaconda3\lib\site-packages\ipykernel_launcher.py:9: RuntimeWarning: divide by zero encountered in log
if name == 'main':
[ 107.09155916 -17.47261277]
减小学习速率,损失函数会有很有更小的值,这就意味着回归函数有更优的拟合。是这样吗,当然不是,我们目的当然是寻找使J(θ)有最小值的θ,然而那是对某一固定速率来讲的。但不同固定速率会导致不同的J(θ)收敛形式。如果收敛过缓,反而会导致低的精度。
n [55]: logitic_fuc(X,Y,alpha=0.0000000065,iteration_1=5000)
上面是预测Y=1时的概率。
比较以上数据,我们发现预测根本就不准。
怎么办呢? 通过编写精确度函数来解决这个问题。
精确度定义=正确预测分类次数/目标集总数
def pricise_func(ary_theo,ar_known):
score=0
bool_1=ary_theo>0.5
bool_2=ar_known==1
bool_2_list=list(bool_2)
nr=bool_2_list.count(True)
for j in range(bool_1.shape[0]):
if bool_1[j] and bool_2[j]:
score+=1
return score/nr
改进精度函数:
def pricise_func(ary_theo,ar_known):
score=0
bool_1=ary_theo>0.5
bool_2=ar_known==1
bool_2_list=list(bool_2)
#nr=bool_2_list.count(True)
for j in range(bool_1.shape[0]):
if (bool_1[j] and bool_2[j])or(not(bool_1[j]) and not(bool_2[j])):
score+=1
return score/len(ar_known)
下面通过它展开我们的训练:训练正确的速率。
trager=0.0001
alpha_opt=0
for i in range(120,220):
alpha_1=i*0.00005
ary_theo=logitic_fuc(X,Y,alpha=alpha_1,iteration_1=3600)
score=pricise_func(ary_theo,Y)
if score>trager:
trager=score
alpha_opt=alpha_1
print(trager,alpha_opt)
0.89 0.006
运行起来太慢,因此分段运行,上面是最佳结果。谁有牛逼计算机,可在家自行操练。
比如运行下面代码,可以得到整个的得分,以及与其对应的alpha值。
#trager=0.0001
#list_score=[]
list_alpha_score=[]
for i in range(120,220):
alpha_1=i*0.0005
ary_theo=logitic_fuc(X,Y,alpha=alpha_1,iteration_1=3600)
list_alpha_score.append((alpha_1,pricise_func(ary_theo,Y)))
list_alpha_score
自己在家运行
下面我们应用牛顿迭代法对其求解,牛顿迭代法的优点
1. 收敛速度极快,往往几步即可搞定,大大提高了运算速率
2. 无需额外设定下降速率
注意:牛顿迭代法是通过产生奇异矩阵来判断训练是否结束,也就是说通过奇异矩阵的产生间接得到最优的回归系数。奇异矩阵一旦产生,将连续持续产生。
def logitic_fuc_newton(X,Y,iteration_1=300):
from scipy import linalg
m,n = X.shape #矩阵大小
#alpha = 0.0065 #设定学习速率
theta_nw = np.zeros(n) #初始化参数
#iteration_1=3000
J = pd.Series(np.zeros(iteration_1, dtype = float)) #构造损失函数承载器
for i in range(iteration_1):
h = logit(np.dot(X, theta_nw)) #回归函数,h是矢量
J[i] = -(1/100.)np.sum(Ynp.log(h)+(1-Y)*np.log(1-h)) #计算损失函数值
#print(J[i])
diff = h - Y #概率差
grad = (1/m)*np.dot(X.T, diff) #梯度,
M=((1/m)h(1-h))*np.identity(m)#中间矩阵
Hesse_matrix=np.dot(X.T,np.dot(M,X))
If linalg.det(Hesse_matrix)==0:
continue
theta_nw -= np.dot(linalg.inv(Hesse_matrix),grad)#牛顿迭代
#J.plot()
#plt.show()
return logit(np.dot(X, theta_nw))
pricise_func(logitic_fuc_newton(X,Y,iteration_1=3000),Y)
Out[18]: 0.9