diff --git a/function.py b/function.py index 19a5da3..bf62866 100644 --- a/function.py +++ b/function.py @@ -1,4 +1,5 @@ import numpy as np +import os # 学号和姓名 id = "202210423130" @@ -17,20 +18,7 @@ def compute_gradient(X_batch, y_batch, weights, lambda_reg): return gradient def train_logreg(X, y, learning_rate=0.001, iterations=10000, batch_size=64, lambda_reg=0.1): - """ - 对率回归训练函数。 - - Args: - - X (numpy array): 特征数据。 - - y (numpy array): 标签数据。 - - learning_rate (float): 学习率。 - - iterations (int): 迭代次数。 - - batch_size (int): 批量大小。 - - lambda_reg (float): L2正则化参数。 - - Returns: - - numpy array: 训练得到的权重。 - """ + """对率回归训练函数。""" m, n = X.shape weights = np.random.randn(n) * np.sqrt(2. / n) # He初始化 for _ in range(iterations): @@ -47,31 +35,16 @@ def train_logreg(X, y, learning_rate=0.001, iterations=10000, batch_size=64, lam return weights def predict_logreg(inX, weights): - """ - 对率回归预测函数。 - - Args: - - inX (numpy array): 输入待分类的样本。 - - weights (numpy array): 训练得到的权重。 - - Returns: - - int: 预测的分类标签。 - """ + """对率回归预测函数。""" z = np.dot(inX, weights) h = sigmoid(z) return 1 if h >= 0.5 else 0 def load_data(filepath): - """ - 从文件中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 - - Args: - - filepath (str): 数据文件路径。 - - Returns: - - np.array: 特征数据。 - - np.array: 标签数据。 - """ + """从文件中加载数据。""" + if not os.path.exists(filepath): + raise FileNotFoundError(f"文件 {filepath} 不存在!") + data, labels = [], [] with open(filepath, 'r') as f: for line in f: @@ -81,47 +54,27 @@ def load_data(filepath): data.append(line_data) labels.append(int(line[-1])) - # 将数据转换为numpy数组 data = np.array(data) labels = np.array(labels) - # 特征选择:去掉特征3(索引2)和特征24~28(索引23到27),检查数据的形状 - num_features = data.shape[1] # 获取特征的总数 - indices_to_remove = [2] # 特征3的索引是2 + num_features = data.shape[1] + indices_to_remove = [2] # 去掉特征3(索引2) - # 仅在数据的特征数量足够时才删除特征24~28 if num_features > 23: - indices_to_remove.extend(range(23, min(28, num_features))) # 从特征24开始到特征28 + indices_to_remove.extend(range(23, min(28, num_features))) data = np.delete(data, indices_to_remove, axis=1) - - # 将标签二分类化,2(死亡)和3(安乐死)合并为0,其余为1 target_variable = np.where((labels == 2) | (labels == 3), 0, 1) return data, target_variable def k_fold_cross_validation(X, y, k=5, learning_rate=0.001, iterations=10000, batch_size=64, lambda_reg=0.1): - """ - K折交叉验证。 - - Args: - - X (numpy array): 特征数据。 - - y (numpy array): 标签数据。 - - k (int): 折数。 - - learning_rate (float): 学习率。 - - iterations (int): 迭代次数。 - - batch_size (int): 批量大小。 - - lambda_reg (float): L2正则化参数。 - - Returns: - - float: 平均准确率。 - """ + """K折交叉验证。""" m = X.shape[0] fold_size = m // k accuracies = [] for i in range(k): - # 创建训练集和验证集 val_start = i * fold_size val_end = (i + 1) * fold_size if i != k - 1 else m @@ -129,26 +82,34 @@ def k_fold_cross_validation(X, y, k=5, learning_rate=0.001, iterations=10000, ba y_val = y[val_start:val_end] X_train = np.concatenate((X[:val_start], X[val_end:])) y_train = np.concatenate((y[:val_start], y[val_end:])) - - # 训练模型 + weights = train_logreg(X_train, y_train, learning_rate, iterations, batch_size, lambda_reg) - # 验证模型 val_accuracy = np.mean([predict_logreg(X_val[j], weights) == y_val[j] for j in range(len(y_val))]) accuracies.append(val_accuracy) + print(f"Fold {i + 1}/{k} - 验证准确率: {val_accuracy:.4f}") + return np.mean(accuracies) if __name__ == "__main__": # 加载训练集 - X_train, y_train = load_data("./data/horse-colic.data") + try: + X_train, y_train = load_data("./data/horse-colic.data") + except FileNotFoundError as e: + print(e) + exit() # k折交叉验证 avg_accuracy = k_fold_cross_validation(X_train, y_train, k=5, learning_rate=0.01, iterations=1000) print(f"K折交叉验证的平均准确率: {avg_accuracy:.4f}") # 加载测试集 - X_test, y_test = load_data("./data/horse-colic.test") + try: + X_test, y_test = load_data("./data/horse-colic.test") + except FileNotFoundError as e: + print(e) + exit() # 训练对率回归模型 weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=1000)