import numpy as np from sklearn.impute import SimpleImputer from sklearn.feature_selection import SelectKBest, f_classif # 填写学号和姓名 id = "202210423206" name = "詹宇豪" def load_data(filepath, k_features=20): """ 从文件中加载数据并进行预处理,包括缺失值填充和特征选择。 Args: - filepath (str): 数据文件路径。 - k_features (int): 选择的特征数量。 Returns: - np.array: 特征数据。 - np.array: 标签数据。 """ data = [] labels = [] with open(filepath, 'r') as file: for line in file: line = line.strip().split() if line: features = [] for feature in line[:-1]: # 最后一个元素是标签 try: features.append(float(feature)) except ValueError: features.append(np.nan) # 用 NaN 表示缺失值 label = int(line[-1]) data.append(features) labels.append(label) # 转换为 numpy 数组 data = np.array(data) labels = np.array(labels) # 使用SimpleImputer填充NaN imputer = SimpleImputer(strategy='mean') data = imputer.fit_transform(data) # 特征标准化,避免除零错误 mean = data.mean(axis=0) std_dev = data.std(axis=0) std_dev[std_dev == 0] = 1 # 如果标准差为0,将其设为1,避免除以零 data = (data - mean) / std_dev # 特征选择 selector = SelectKBest(f_classif, k=k_features) data = selector.fit_transform(data, labels) return data, labels def sigmoid(z): """ Sigmoid激活函数,用于对率回归模型。 Args: - z (numpy array): 输入数据。 Returns: - numpy array: Sigmoid函数输出值。 """ return 1 / (1 + np.exp(-z)) 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): 学习率衰减系数。 Returns: - numpy array: 训练得到的权重。 """ m, n = X.shape weights = np.zeros(n) learning_rate = initial_lr for i in range(iterations): z = np.dot(X, weights) predictions = sigmoid(z) errors = y - predictions gradient = np.dot(X.T, errors) / m - regularization * weights / m weights += learning_rate * gradient # 学习率衰减 learning_rate = initial_lr / (1 + decay * i) return weights def predict_logreg(inX, weights, threshold=0.5): """ 对率回归预测函数,包含可调阈值。 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__": # 加载数据并选择前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) # 训练模型 weights = train_logreg(X_train, y_train, initial_lr=0.005, iterations=5000, regularization=0.01, decay=0.0001) # 模型评估 correct_predictions = 0 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}")