From: https://github.com/L1aoXingyu/code-of-learn-deep-learning-with-pytorch
Logistic 回归是一种广义的回归模型,其与多元线性回归有着很多相似之处,模型的形式基本相同,虽然也被称为回归,但是其更多的情况使用在分类问题上,同时又以二分类更为常用。
Logistic 回归的模型形式和线性回归一样,都是 y = wx + b,其中 x 可以是一个多维的特征,唯一不同的地方在于 Logistic 回归会对 y 作用一个 logistic(Sigmoid ) 函数,将其变为一种概率的结果。
sigmoid:
数据
data = pd.read_csv('data/logistic_demo.txt', header=None)
标准化
# 标准化
data[0] = data[0]/data[0].max()
data[1] = data[1]/data[1].max()
x0 = data[data[2]==0]
x1 = data[data[2]==1]
plt.plot(x0[0], x0[1], 'ro', label='x_0')
plt.plot(x1[0], x1[1], 'bo', label='x_1')
plt.legend()
训练数据
x_train = torch.from_numpy(data[[0, 1]].values).float() # [100, 2]
y_train = torch.from_numpy(data[[2]].values).float() # [100, 1]
x_train = Variable(x_train)
y_train = Variable(y_train)
w = Variable(torch.randn(2, 1), requires_grad=True)
b = Variable(torch.ones(1), requires_grad=True)
初始参数拟合
w0 = w[0].data[0].numpy()
w1 = w[1].data[0].numpy()
b0 = b.data[0].numpy()
plt_x = np.arange(0.2, 1, 0.01)
plt_y = (-w0 * plt_x - b0) / w1
plt.plot(plt_x, plt_y, 'g', label='line')
plt.plot(x0[0], x0[1], 'ro', label='x_0')
plt.plot(x1[0], x1[1], 'bo', label='x_1')
plt.legend()
自定义模型&损失拟合
# 模型
def logistic_model(x):
return F.sigmoid(torch.matmul(x, w) + b)
# 损失
def binary_loss(y_train, y_predict):
logist = (y_train*y_predict.clamp(1e-12).log() +
(1-y_train)*(1-y_predict).clamp(1e-12).log()).mean()
return -logist
y_predict = logistic_model(x_train)
loss = binary_loss(y_train, y_predict)
print(loss)
# 更新参数
loss.backward()
w.data = w.data - 0.1 * w.grad.data
b.data = b.data - 0.1 * b.grad.data
y_predict = logistic_model(x_train)
loss = binary_loss(y_train, y_predict)
print(loss)
tensor(0.9453, grad_fn=<NegBackward>)
tensor(0.9303, grad_fn=<NegBackward>)
使用torch.optim 更新参数
from torch import nn
w = nn.Parameter(torch.randn(2, 1))
b = nn.Parameter(torch.ones(1))
def logistic_model(x):
return F.sigmoid(torch.matmul(x, w) + b)
optimizer = torch.optim.SGD([w ,b], lr=1.0)
for i in range(1000):
y_predict = logistic_model(x_train)
loss = binary_loss(y_train, y_predict)
optimizer.zero_grad() # 梯度归零
loss.backward()
optimizer.step() # 使用优化器更新参数
mask = y_predict.ge(0.5).float()
acc = (mask == y_train).sum().data.numpy() / y_train.shape[0]
if (i+1) % 200 == 0:
print('epoch: {}, Loss: {:.5f}, Acc: {:.5f}'.format(i+1, loss.data, acc))
w0 = w[0].data[0].numpy()
w1 = w[1].data[0].numpy()
b0 = b.data[0].numpy()
plt_x = np.arange(0.2, 1, 0.01)
plt_y = (-w0 * plt_x - b0) / w1
plt.plot(plt_x, plt_y, 'g', label='line')
plt.plot(x0[0], x0[1], 'ro', label='x_0')
plt.plot(x1[0], x1[1], 'bo', label='x_1')
plt.legend()
epoch: 200, Loss: 0.21615, Acc: 0.89000
epoch: 400, Loss: 0.21497, Acc: 0.89000
epoch: 600, Loss: 0.21393, Acc: 0.89000
epoch: 800, Loss: 0.21301, Acc: 0.89000
epoch: 1000, Loss: 0.21219, Acc: 0.89000
使用torch自带loss¶
w = nn.Parameter(torch.randn(2, 1))
b = nn.Parameter(torch.ones(1))
def logistic_model(x):
return F.sigmoid(torch.matmul(x, w) + b)
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.SGD([w, b], lr=1.0)
for i in range(1000):
# 预测, 计算损失
y_predict = logistic_model(x_train)
loss = criterion(y_predict, y_train)
# 优化参数
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 计算准确率
mask = y_predict.ge(0.5).float()
acc = (mask == y_train).sum().data.numpy() / y_train.shape[0]
if (i+1)%200 == 0:
print('epoch: {}, Loss: {:.5f}, Acc: {:.5f}'.format(i+1, loss.data, acc))
w0 = w[0].data[0].numpy()
w1 = w[1].data[0].numpy()
b0 = b.data[0].numpy()
plt_x = np.arange(0.2, 1, 0.01)
plt_y = (-w0 * plt_x - b0) / w1
plt.plot(plt_x, plt_y, 'g', label='line')
plt.plot(x0[0], x0[1], 'ro', label='x_0')
plt.plot(x1[0], x1[1], 'bo', label='x_1')
plt.legend()
epoch: 200, Loss: 0.64844, Acc: 0.80000
epoch: 400, Loss: 0.62356, Acc: 0.87000
epoch: 600, Loss: 0.60547, Acc: 0.88000
epoch: 800, Loss: 0.59237, Acc: 0.88000
epoch: 1000, Loss: 0.58266, Acc: 0.88000