学习笔记 | 逻辑回归模型
逻辑回归模型代码
#逻辑回归
# 预测函数采用sigmoid类型
# 代价函数采用新的极大似然估计函数
# 优化代价函数思路采用梯度下降
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
#import math math库不适用,直接使用numpy库
#首先导入数据
df=pd.read_csv("file4logreg.csv")
#将所需数据矩阵化
X=df[["age","income","education"]].values
y=df[["results"]].values #标签值
#将数据标准化
X_scaler=StandardScaler()
X_scaled=X_scaler.fit_transform(X)
# 错误:y不用标准化,y_scaled=y_scaler.fit_transform(y)
#因为在分类问题中,y作为标签只有0和1两个取值
#设置维度
m,n=X_scaled.shape
#设置线性部分参数w,b
w=np.zeros((n,1))
b=0.0
#设置学习率与循环次数
lr=0.01
epochs=1000
#设置sigmoid函数
def sigmoid( a ):
sig=1/(1+np.exp(-a))
return sig
#开始梯度下降
for epoch in range(epochs):
#计算线性部分
y_line=X_scaled@w+b
#计算sigmoid输出
y_pred=sigmoid(y_line)
#计算简化损失与代价函数
loss=-y*np.log(y_pred)-(1-y)*np.log(1-y_pred)
cost=np.mean(loss)
#计算w,b的梯度
w_grad=1/m*X_scaled.T@(y_pred-y)
b_grad=1/m*np.sum(y_pred-y)
#更新
w=w-lr*w_grad
b=b-lr*b_grad
if(epoch%100==0):
print(f"Epoch: {epoch},Cost: {cost:.6f}")
print(f"Final w: {w.ravel()}, b: {b:.6f}") # .ravel() 展平打印
1.*本身就是逐元素相乘,并且要求两个向量是同一类型的
向量化的目的是为了加速,符合底层运算
在 NumPy 的世界里,你写 -y * np.log(y_pred) 这种表达式,它自动就给你逐元素干了——就像你把每个样本单独拎出来算一遍,但 NumPy 用 C 语言在底层帮你循环,快得飞起。
所以你只要按“单个样本的逻辑”写公式,NumPy 会自动把向量喂进去,逐个元素算,然后吐出一个同形状的向量。 你完全不需要手动写 for i in range(m),那种写法又慢又蠢,是给菜鸟用的。
两个坑:
· 矩阵乘法不是逐元素:@ 或 np.dot 是线性代数乘法,不是 *(逐元素乘),别搞混。
· 广播规则:如果你操作的两个向量形状不一致(比如 (m,1) 和 (m,)),NumPy 会尝试广播,有时会得到意想不到的结果。最好保证形状明确,比如都用 (m,1) 列向量,省得闹鬼。
2.代码中的梯度形式于分析中的梯度形式有所不同,有点小差异,各有各的美
由于代码逻辑中是向量运算,所以w的梯度在向量点乘的时候自然相加了,无需b的梯度中类似的sum操作

浙公网安备 33010602011771号