# function.py import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split, KFold """ 实验说明: - 自行编写实现数据加载与预测病马死亡的对率回归算法。 注意事项: - 在 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 = "202210423209" name = "万子玉" # 这里写自己的代码实现 def sigmoid(z): return 1 / (1 + np.exp(-z)) def train_logreg(X, y, learning_rate=0.01, iterations=2000, lambda_reg=0.01, batch_size=32): X = np.insert(X, 0, 1, axis=1) # 添加偏置项 m, n = X.shape weights = np.random.randn(n) * 0.01 # 随机初始化权重 for i in range(iterations): indices = np.arange(m) np.random.shuffle(indices) X_shuffled = X[indices] y_shuffled = y[indices] for j in range(0, m, batch_size): X_batch = X_shuffled[j:j + batch_size] y_batch = 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 # 更新权重 weights -= learning_rate * gradient return weights """ 对率回归训练函数。 Args: - X (numpy array): 特征数据。 - y (numpy array): 标签数据。 - other_params (str): 其它参数,可选设置。若需设置其它参数,必须设置其默认值,否则将**无法通过**自动评测,**成绩为零**。 Returns: - numpy array: 训练得到的权重。 """ def predict_logreg(inX, weights): inX = np.insert(inX, 0, 1) # 添加偏置项 z = np.dot(inX, weights) prediction_prob = sigmoid(z) return 1 if prediction_prob >= 0.5 else 0 """ 对率回归预测函数。 Args: - inX (numpy array): 输入待分类的样本。 - weights (numpy array): 训练得到的权重。 Returns: - int: 预测的分类标签。 """ def evaluate_model(X_val, y_val, weights): predictions = np.array([predict_logreg(x, weights) for x in X_val]) accuracy = np.mean(predictions == y_val) return accuracy def split_train_val(X, y, val_size=0.2): shuffled_indices = list(range(X.shape[0])) random.shuffle(shuffled_indices) X_shuffled = X[shuffled_indices] y_shuffled = y[shuffled_indices] val_count = int(X.shape[0] * val_size) X_val = X_shuffled[:val_count] y_val = y_shuffled[:val_count] X_train = X_shuffled[val_count:] y_train = y_shuffled[val_count:] return X_train, X_val, y_train, y_val # 这里也写自己的代码实现 def load_data(filepath): with open(filepath, 'r') as file: lines = file.readlines() data = [line.strip().split() for line in lines if line.strip().split()[-1].isdigit()] data = [list(map(lambda x: float(x) if x != '?' else np.nan, row)) for row in data] # 移除类别标签缺失的样本 data = [row for row in data if not np.isnan(row[-1])] # 使用“0”填充缺失值 for row in data: for i in range(len(row)): if np.isnan(row[i]): row[i] = 0.0 # 合并特征23的值2和3为0 for row in data: if row[22] == 2 or row[22] == 3: # 假设特征23是第23个元素 row[22] = 0 # 移除不需要的特征 data = [row[:2] + row[3:23] + row[28:] for row in data] # 分离特征和标签 X = [row[:-1] for row in data] y = [row[-1] for row in data] scaler = StandardScaler() X = scaler.fit_transform(X) return np.array(X), np.array(y) """ 从文件中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 Args: - directory (str): 数据文件路径。 Returns: - np.array: 特征数据。 - np.array: 标签数据。 """ if __name__ == "__main__": X_train, y_train = load_data("./data/horse-colic.data") X_test, y_test = load_data("./data/horse-colic.test") weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=2000) y_pred = predict_logreg(X_test[11], weights) print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}")