diff --git a/function.py b/function.py index 2966450..61f82d1 100644 --- a/function.py +++ b/function.py @@ -1,137 +1,63 @@ import numpy as np from sklearn.impute import SimpleImputer -from sklearn.feature_selection import SelectKBest, mutual_info_classif -from sklearn.preprocessing import RobustScaler +from sklearn.feature_selection import SelectKBest, f_classif # 填写学号和姓名 id = "202210423213" name = "熊浩燃" def load_data(filepath, k_features=20): - """ - 从文件中加载数据并进行预处理,包括缺失值填充和特征选择。 - - Args: - - filepath (str): 数据文件路径。 - - k_features (int): 选择的特征数量。 - - Returns: - - np.array: 特征数据。 - - np.array: 标签数据。 - """ - data = [] - labels = [] + 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 表示缺失值 + features = [float(feature) if feature.replace('.', '', 1).isdigit() else np.nan for feature in line[:-1]] label = int(line[-1]) data.append(features) labels.append(label) - # 转换为 numpy 数组 - data = np.array(data) - labels = np.array(labels) - - # 使用SimpleImputer填充NaN - imputer = SimpleImputer(strategy='median') + data, labels = np.array(data), np.array(labels) + imputer = SimpleImputer(strategy='mean') 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进行数据标准化,减少异常值的影响 - scaler = RobustScaler() - data = scaler.fit_transform(data) - - # 特征选择,使用互信息 - selector = SelectKBest(mutual_info_classif, k=k_features) + selector = SelectKBest(f_classif, k=k_features) data = selector.fit_transform(data, labels) return data, labels def sigmoid(z): - """Sigmoid激活函数""" 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): - """ - 对率回归训练函数,包含学习率衰减和早停机制。 - - Args: - - X (numpy array): 特征数据。 - - y (numpy array): 标签数据。 - - initial_lr (float): 初始学习率。 - - iterations (int): 迭代次数。 - - regularization (float): 正则化强度。 - - decay (float): 学习率衰减系数。 - - patience (int): 早停的等待次数。 - - Returns: - - numpy array: 训练得到的权重。 - """ +def train_logreg(X, y, initial_lr=0.005, iterations=5000, regularization=0.01, decay=0.0001): m, n = X.shape weights = np.zeros(n) - best_loss = float('inf') - stop_counter = 0 + learning_rate = initial_lr for i in range(iterations): - # 前向传播和损失计算 - 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 - - # 反向传播更新权重 + predictions = sigmoid(np.dot(X, weights)) errors = y - predictions - gradient = np.dot(X.T, errors) / m - regularization * weights / m - weights += initial_lr * gradient / (1 + decay * i) # 学习率衰减 + gradient = (np.dot(X.T, errors) - 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 +def predict_logreg(X, weights, threshold=0.5): + probabilities = sigmoid(np.dot(X, weights)) + return (probabilities >= threshold).astype(int) # 测试代码 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.01, iterations=5000, regularization=0.02, decay=0.00005, patience=200) + 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) + y_pred = predict_logreg(X_test, weights, threshold=0.5) + accuracy = np.mean(y_pred == y_test) print(f"测试集准确率: {accuracy:.2f}")