Files
Experiment-LogReg/function.py
T
zhangchenghong e2f5b6ad04
Gitea Actions Experiment Test / Experiment-Actions (push) Successful in 25s
更新 function.py
2024-11-02 14:13:04 +08:00

128 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import numpy as np
"""
实验说明:
- 自行编写实现数据加载与预测病马死亡的对率回归算法。
注意事项:
- 在 function.py 中实现对率回归算法。
- 可以自行导入其他库,需要在 requirements.txt 添加依赖,若未在 requirements.txt 中添加使用到的依赖,则无法自动评测,成绩为零。
- 自动评测脚本仅会加载 train_logreg、predict_logreg 和 load_data 函数,请勿修改函数名。
测评环境:
- CPU: Intel Xeon(R) CPU E3-1231 v3 @ 3.40GHz
- OS: Ubuntu 22.04.4 LTS
- Python: 3.10.12
- numpy: 2.1.1
"""
"""
请在这里填写学号和姓名,不填写即成绩无效。
"""
id = "202210423215"
name = "章程鸿"
# 这里写自己的代码实现
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
def sigmoid(z):
"""Sigmoid 激活函数。"""
return 1 / (1 + np.exp(-z))
def train_logreg(X, y, learning_rate=0.01, iterations=1000, lambda_reg=0.01, batch_size=32):
"""逻辑回归训练函数,随机初始化权重,并在每次迭代前打乱数据。"""
m, n = X.shape
weights = np.random.randn(n) * 0.01 # 随机初始化权重,取较小值
for i in range(iterations):
# 每次迭代打乱数据
indices = np.random.permutation(m)
X = X[indices]
y = y[indices]
for j in range(0, m, batch_size): # 按照 batch size 迭代
X_batch = X[j:j + batch_size]
y_batch = y[j:j + batch_size]
z = np.dot(X_batch, weights)
predictions = sigmoid(z)
gradient = np.dot(X_batch.T, (predictions - y_batch)) / X_batch.shape[0]
# L2正则化
gradient += (lambda_reg / m) * weights
# 更新权重
weights -= learning_rate * gradient
# 动态调整学习率,逐渐减小
learning_rate *= 0.99
return weights
def predict_logreg(inX, weights):
"""逻辑回归预测函数。"""
z = np.dot(inX, weights)
prediction_prob = sigmoid(z)
return 1 if prediction_prob >= 0.5 else 0
def load_data(filepath):
"""加载数据并处理缺失值。"""
data = []
labels = []
with open(filepath, 'r') as f:
for line in f:
values = line.strip().replace('?', '0').split()
try:
values = [float(v) for v in values]
# 合并特征23的取值
if values[22] == 2 or values[22] == 3: # 特征23(索引22)
labels.append(0) # 死亡
elif values[22] == 1:
labels.append(1) # 生存
else:
continue # 无效标签,丢弃
# 用0填充缺失值
values = [0 if v == 0 else v for v in values] # 直接用0填充
data.append(values[:2] + values[3:23]) # 保留特征1, 2 和特征4-23
except ValueError:
continue
data = np.array(data)
labels = np.array(labels)
return data, labels
def preprocess_data(X):
"""特征标准化。"""
scaler = StandardScaler()
return scaler.fit_transform(X)
if __name__ == "__main__":
# 加载数据集
X, y = load_data("./data/horse-colic.data")
# 归一化数据
X = preprocess_data(X)
# 使用 train_test_split 打乱并随机抽取数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练逻辑回归模型,设置 batch size
batch_size = 32
weights = train_logreg(X_train, y_train, learning_rate=0.1, iterations=1000, lambda_reg=0.01, batch_size=batch_size)
# 测试单个数据
y_pred = predict_logreg(X_test[11], weights)
print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}")