更新 function.py
Gitea Actions Experiment Test / Experiment-Actions (push) Successful in 30s

This commit is contained in:
2024-10-31 17:06:31 +08:00
parent 9dca6c1a94
commit 53fe98a281
+22 -96
View File
@@ -1,137 +1,63 @@
import numpy as np import numpy as np
from sklearn.impute import SimpleImputer from sklearn.impute import SimpleImputer
from sklearn.feature_selection import SelectKBest, mutual_info_classif from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.preprocessing import RobustScaler
# 填写学号和姓名 # 填写学号和姓名
id = "202210423213" id = "202210423213"
name = "熊浩燃" name = "熊浩燃"
def load_data(filepath, k_features=20): def load_data(filepath, k_features=20):
""" data, labels = [], []
从文件中加载数据并进行预处理,包括缺失值填充和特征选择。
Args:
- filepath (str): 数据文件路径。
- k_features (int): 选择的特征数量。
Returns:
- np.array: 特征数据。
- np.array: 标签数据。
"""
data = []
labels = []
with open(filepath, 'r') as file: with open(filepath, 'r') as file:
for line in file: for line in file:
line = line.strip().split() line = line.strip().split()
if line: if line:
features = [] features = [float(feature) if feature.replace('.', '', 1).isdigit() else np.nan for feature in line[:-1]]
for feature in line[:-1]: # 最后一个元素是标签
try:
features.append(float(feature))
except ValueError:
features.append(np.nan) # 用 NaN 表示缺失值
label = int(line[-1]) label = int(line[-1])
data.append(features) data.append(features)
labels.append(label) labels.append(label)
# 转换为 numpy 数组 data, labels = np.array(data), np.array(labels)
data = np.array(data) imputer = SimpleImputer(strategy='mean')
labels = np.array(labels)
# 使用SimpleImputer填充NaN
imputer = SimpleImputer(strategy='median')
data = imputer.fit_transform(data) data = imputer.fit_transform(data)
mean, std_dev = data.mean(axis=0), data.std(axis=0)
std_dev[std_dev == 0] = 1
data = (data - mean) / std_dev
# 使用RobustScaler进行数据标准化,减少异常值的影响 selector = SelectKBest(f_classif, k=k_features)
scaler = RobustScaler()
data = scaler.fit_transform(data)
# 特征选择,使用互信息
selector = SelectKBest(mutual_info_classif, k=k_features)
data = selector.fit_transform(data, labels) data = selector.fit_transform(data, labels)
return data, labels return data, labels
def sigmoid(z): def sigmoid(z):
"""Sigmoid激活函数"""
return 1 / (1 + np.exp(-z)) return 1 / (1 + np.exp(-z))
def train_logreg(X, y, initial_lr=0.01, iterations=5000, regularization=0.02, decay=0.00005, patience=200): def train_logreg(X, y, initial_lr=0.005, iterations=5000, regularization=0.01, decay=0.0001):
"""
对率回归训练函数,包含学习率衰减和早停机制。
Args:
- X (numpy array): 特征数据。
- y (numpy array): 标签数据。
- initial_lr (float): 初始学习率。
- iterations (int): 迭代次数。
- regularization (float): 正则化强度。
- decay (float): 学习率衰减系数。
- patience (int): 早停的等待次数。
Returns:
- numpy array: 训练得到的权重。
"""
m, n = X.shape m, n = X.shape
weights = np.zeros(n) weights = np.zeros(n)
best_loss = float('inf') learning_rate = initial_lr
stop_counter = 0
for i in range(iterations): for i in range(iterations):
# 前向传播和损失计算 predictions = sigmoid(np.dot(X, weights))
z = np.dot(X, weights)
predictions = sigmoid(z)
loss = -np.mean(y * np.log(predictions + 1e-9) + (1 - y) * np.log(1 - predictions + 1e-9)) + regularization * np.sum(weights ** 2) / (2 * m)
# 早停机制
if loss < best_loss:
best_loss = loss
stop_counter = 0
else:
stop_counter += 1
if stop_counter >= patience:
print("早停:在第 {} 轮迭代停止".format(i))
break
# 反向传播更新权重
errors = y - predictions errors = y - predictions
gradient = np.dot(X.T, errors) / m - regularization * weights / m gradient = (np.dot(X.T, errors) - regularization * weights) / m
weights += initial_lr * gradient / (1 + decay * i) # 学习率衰减 weights += learning_rate * gradient
learning_rate = initial_lr / (1 + decay * i)
return weights return weights
def predict_logreg(inX, weights, threshold=0.5): def predict_logreg(X, weights, threshold=0.5):
""" probabilities = sigmoid(np.dot(X, weights))
对率回归预测函数,包含可调阈值。 return (probabilities >= threshold).astype(int)
Args:
- inX (numpy array): 输入待分类的样本。
- weights (numpy array): 训练得到的权重。
- threshold (float): 判定阈值,默认为0.5。
Returns:
- int: 预测的分类标签。
"""
probability = sigmoid(np.dot(inX, weights))
return 1 if probability >= threshold else 2
# 测试代码 # 测试代码
if __name__ == "__main__": if __name__ == "__main__":
# 加载数据并选择前20个最重要的特征
X_train, y_train = load_data("./data/horse-colic.data", k_features=20) X_train, y_train = load_data("./data/horse-colic.data", k_features=20)
X_test, y_test = load_data("./data/horse-colic.test", k_features=20) X_test, y_test = load_data("./data/horse-colic.test", k_features=20)
# 训练模型 weights = train_logreg(X_train, y_train, initial_lr=0.005, iterations=5000, regularization=0.01, decay=0.0001)
weights = train_logreg(X_train, y_train, initial_lr=0.01, iterations=5000, regularization=0.02, decay=0.00005, patience=200)
# 模型评估 y_pred = predict_logreg(X_test, weights, threshold=0.5)
correct_predictions = 0 accuracy = np.mean(y_pred == y_test)
for i in range(len(X_test)):
y_pred = predict_logreg(X_test[i], weights, threshold=0.5)
if y_pred == y_test[i]:
correct_predictions += 1
print(f"预测结果: {y_pred}, 实际结果: {y_test[i]}")
accuracy = correct_predictions / len(X_test)
print(f"测试集准确率: {accuracy:.2f}") print(f"测试集准确率: {accuracy:.2f}")