仅使用python+numpy实现的逻辑回归模型
代码库Github链接为:https://github.com/Resulte/logistic-regression-model
(希望您去Github的时候可以顺手给个Star)
数据集说明
数据集在dataset目录下,分为下面三个文件
-
trainset.json: 内包含训练集数据,由1000条数据组成的列表,每条数据由一组输入数据和一个label值,输入数据为一个长度为9的数组,label为0则代表该输入数据属于第0类,label为1则代表该输入数据属于第1类。
-
devset.json: 内包含验证集数据,格式同trainset.json,由200条数据组成的列表,每条数据由一组输入数据和一个label值,输入数据为一个长度为9的数组,label为0则代表该输入数据属于第0类,label为1则代表该输入数据属于第1类。
-
testset.json: 内包含测试数据,是一个由100条测试数据组成的二维数组,形状为[100,9]
模型说明
本模型将会采用 梯度下降法 训练一个逻辑回归模型,并使用此模型对testset.json中的数据进行预测。
在完成函数拟合后,将会使用得出的二分类模型对testset.json中的100条测试数据进行预测,并将此文件补充为与trainset.json相同格式的文件。
本算法只会采用python的numpy库自行实现模型的训练和测试。
第一步:加载数据集
# 加载数据集
def load_data(dirname = TRAIN_DIR):
data = []
with open(dirname, "r") as data_file:
data = json.load(data_file)
data_x = [i[0] for i in data]
data_y = [i[1] for i in data]
return np.array(data_x), np.array(data_y)
第二步:训练模型
训练模型的时候可以同时画训练集&验证集的loss曲线,还有计算训练集&验证集的准确率。
# 激活函数
def sigmoid(z):
return 1 / (1+ np.exp(-z))
# 回归模型
def model(data_x, weights):
return sigmoid(np.dot(data_x, weights.T))
# 损失值计算
def loss(data_x, data_y, weights):
model_value = model(data_x, weights).ravel()
left = np.multiply(-data_y, np.log(model_value))
right = np.multiply(1 - data_y, np.log(1 - model_value))
return np.mean(left - right)
# 梯度计算
def gradient(data_x, data_y, weights):
grad = np.zeros(weights.shape)
error = (model(data_x, weights)).ravel() - data_y
for j in range(len(weights.ravel())):
term = np.multiply(error, data_x[:, j])
grad[0, j] = np.sum(term) / len(data_x)
return grad
# loss曲线绘画
def draw_loss(train_loss, valid_loss):
plt.plot(train_loss, c='b', label='train loss')
plt.plot(valid_loss, c='r', label='valid loss')
plt.legend(loc=0, ncol=1)
plt.xlabel('iternations')
plt.ylabel('loss')
plt.savefig('./train和valid的loss曲线图.png')
plt.show()
# 模型预测值计算
def predict(data_x, weights):
return [1 if x > 0.5 else 0 for x in model(data_x, weights)]
# 准确率计算
def accuracy(real_val, predict_val):
correct = [1 if real_val[i] == predict_val[i] else 0 for i in range(len(real_val))]
return np.sum(correct) / len(real_val)
# 训练模型
def train(batchSize, threshold, learning_rate):
batch = 0
epoch = 0
# 加载训练&验证集
train_x, train_y = load_data(TRAIN_DIR)
valid_x, valid_y = load_data(VALID_DIR)
# 初始化weights
weights = np.zeros((1, train_x.shape[1]))
# 初始化loss
train_loss = [loss(train_x, train_y, weights)]
valid_loss = [loss(valid_x, valid_y, weights)]
# 初始化梯度
grad = np.zeros(weights.shape)
# 梯度下降
while True:
grad = gradient(train_x[batch : batch + batchSize], train_y[batch : batch + batchSize], weights)
# 参数更新
weights = weights - learning_rate * grad
train_loss.append(loss(train_x, train_y, weights))
valid_loss.append(loss(valid_x, valid_y, weights))
epoch += 1
if epoch > threshold:
break;
# 画训练集&验证集的loss曲线
draw_loss(train_loss, valid_loss)
# 计算训练集&验证集的准确率
print("训练集准确率:", accuracy(train_y, predict(train_x, weights)))
print("验证集准确率:", accuracy(valid_y, predict(valid_x, weights)))
return weights
第三步:测试模型
测试的时候,需要预测数据集:
# 测试模型
def test(weights):
# 加载测试集
test_data = []
with open(TEST_DIR, "r") as data_file:
test_data = json.load(data_file)
test_data = np.array(test_data)
# 预测测试集
test_predict = predict(test_data, weights)
# 输出测试结果
new_test_data=[[test_data[i].tolist(), test_predict[i]] for i in range(len(test_predict))]
with open(OUTPUT_DIR, "w") as file:
json.dump(new_test_data, file)
输出结果
训练集&验证集的loss曲线图如下:
准确率为:
训练集准确率: 0.826
验证集准确率: 0.825