diff --git a/function.py b/function.py index 6835dec..0acbd86 100644 --- a/function.py +++ b/function.py @@ -25,49 +25,45 @@ from sklearn.model_selection import train_test_split, KFold id = "202210423117" name = "程悦" +import numpy as np +from sklearn.preprocessing import StandardScaler +from sklearn.model_selection import train_test_split, KFold + +# 学号和姓名 +id = "202210423117" +name = "程悦" + def sigmoid(z): - """Sigmoid 激活函数。""" + """计算Sigmoid激活函数值""" return 1 / (1 + np.exp(-z)) def train_logreg(X, y, learning_rate=0.1, iterations=2000, lambda_reg=0.01, batch_size=32): - """逻辑回归训练函数,随机初始化权重,并在每次迭代前打乱数据。""" + """训练逻辑回归模型""" m, n = X.shape - weights = np.random.randn(n) * 0.01 # 随机初始化权重,取较小值 + weights = np.random.randn(n) * 0.01 - for i in range(iterations): - # 每次迭代打乱数据 + for _ in range(iterations): indices = np.random.permutation(m) - X_shuffled = X[indices] - y_shuffled = y[indices] - - for j in range(0, m, batch_size): # 按照 batch size 迭代 - X_batch = X_shuffled[j:j + batch_size] - y_batch = y_shuffled[j:j + batch_size] + X_shuffled, y_shuffled = X[indices], y[indices] + for j in range(0, m, batch_size): + X_batch, y_batch = X_shuffled[j:j + batch_size], y_shuffled[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 - - # 更新权重 + gradient = np.dot(X_batch.T, (predictions - y_batch)) / batch_size + gradient += (lambda_reg / m) * weights # L2正则化 weights -= learning_rate * gradient - # 动态调整学习率,逐渐减小 - if i % 100 == 0: - learning_rate *= 0.95 + learning_rate *= 0.95 if _ % 100 == 0 else 1 # 动态调整学习率 return weights def predict_logreg(X, weights): - """逻辑回归预测函数。""" - z = np.dot(X, weights) - prediction_prob = sigmoid(z) - return np.where(prediction_prob >= 0.5, 1, 0) + """使用逻辑回归模型进行预测""" + return (sigmoid(np.dot(X, weights)) >= 0.5).astype(int) def load_data(filepath): - """加载数据并处理缺失值。""" + """加载数据并处理缺失值""" data, labels = [], [] with open(filepath, 'r') as f: @@ -75,69 +71,38 @@ def load_data(filepath): values = line.strip().replace('?', '0').split() try: values = [float(v) for v in values] - - # 合并特征23的取值 - if values[22] in [2, 3]: # 特征23(索引22) - labels.append(0) # 死亡 - elif values[22] == 1: - labels.append(1) # 生存 - else: - continue # 无效标签,丢弃 - - # 用0填充缺失值并提取特征 - data.append([0 if v == 0 else v for v in values[:2] + values[3:23]]) # 保留特征1, 2 和特征4-23 + if values[22] in [1, 2, 3]: + labels.append(0 if values[22] in [2, 3] else 1) + data.append([0 if v == 0 else v for v in values[:2] + values[3:23]]) except ValueError: continue data = np.array(data) labels = np.array(labels) - - # 数据标准化 - scaler = StandardScaler() - data = scaler.fit_transform(data) - - return data, labels + return StandardScaler().fit_transform(data), labels def accuracy(X, y, weights): - """计算模型准确率。""" - predictions = predict_logreg(X, weights) - return np.mean(predictions == y) + """计算模型准确率""" + return np.mean(predict_logreg(X, weights) == y) if __name__ == "__main__": - # 加载训练集 - X_train, y_train = load_data("./horse-colic.data") - - # 使用 train_test_split 打乱并随机抽取训练和验证数据 + X_train, y_train = load_data("./data/horse-colic.data") X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42) - # K折交叉验证 - k = 5 - kf = KFold(n_splits=k, shuffle=True, random_state=42) - accuracies = [] + kf = KFold(n_splits=5, shuffle=True, random_state=42) + accuracies = [accuracy(X_val_kf, y_val_kf, train_logreg(X_train_kf, y_train_kf, batch_size=32)) + for train_index, val_index in kf.split(X_train) + for X_train_kf, X_val_kf in [(X_train[train_index], X_train[val_index])] + for y_train_kf, y_val_kf in [(y_train[train_index], y_train[val_index])]] - for train_index, val_index in kf.split(X_train): - X_train_kf, X_val_kf = X_train[train_index], X_train[val_index] - y_train_kf, y_val_kf = y_train[train_index], y_train[val_index] - - # 训练逻辑回归模型,设置 batch size - weights = train_logreg(X_train_kf, y_train_kf, learning_rate=0.1, iterations=2000, lambda_reg=0.01, batch_size=32) - - # 验证模型 - val_accuracy = accuracy(X_val_kf, y_val_kf, weights) - accuracies.append(val_accuracy) - - # 输出交叉验证的准确率和平均准确率 print(f"K折交叉验证得分: {accuracies}") print(f"平均准确率: {np.mean(accuracies):.4f}") - # 加载测试集 - X_test, y_test = load_data("./horse-colic.test") - - # 在测试集上评估最终模型 - final_weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=1000, lambda_reg=0.01, batch_size=32) + X_test, y_test = load_data("./data/horse-colic.test") + final_weights = train_logreg(X_train, y_train, batch_size=32) test_accuracy = accuracy(X_test, y_test, final_weights) print(f"测试集的准确率: {test_accuracy:.4f}") # 测试单个数据 y_pred = predict_logreg(X_test[11], final_weights) - print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}") \ No newline at end of file + print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}")