diff --git a/function.py b/function.py index 587a7e6..18a5fa2 100644 --- a/function.py +++ b/function.py @@ -1,98 +1,73 @@ import numpy as np -""" -实验说明: -- 自行编写实现数据加载与预测病马死亡的对率回归算法。 -""" - id = "202210423218" name = "唐一鸣" -def load_data(filepath): - """ - 从文件中加载数据。 - - Args: - - filepath (str): 数据文件路径。 - - Returns: - - np.array: 特征数据。 - - np.array: 标签数据。 - """ - data = [] - labels = [] - - with open(filepath, 'r') as file: - for line in file: - # 用空格分割每一行 - parts = line.strip().split() - # 将特征和标签分开,假设最后一列为标签 - features = parts[:-1] - label = parts[-1] - - # 用-1替换缺失值(或你可以选择其他处理方式) - features = [float(x) if x != '?' else -1 for x in features] - data.append(features) - labels.append(int(label)) - - return np.array(data), np.array(labels) - def sigmoid(z): - """Sigmoid 激活函数""" return 1 / (1 + np.exp(-z)) -def train_logreg(X, y, learning_rate=0.01, iterations=1000): - """ - 对率回归训练函数。 - - Args: - - X (numpy array): 特征数据。 - - y (numpy array): 标签数据。 - - learning_rate (float): 学习率。 - - iterations (int): 迭代次数。 - - Returns: - - numpy array: 训练得到的权重。 - """ +def train_logreg(X, y, learning_rate=0.01, iterations=1000, batch_size=128, lambda_reg=0.01): m, n = X.shape weights = np.zeros(n) - - for _ in range(iterations): - linear_model = np.dot(X, weights) - predictions = sigmoid(linear_model) - # 计算梯度 - gradient = np.dot(X.T, (predictions - y)) / m - weights -= learning_rate * gradient + for j in range(iterations): + dataIndex = np.random.permutation(m) + for i in range(0, m, batch_size): + end = min(i + batch_size, m) + batch_X = X[dataIndex[i:end]] + batch_y = y[dataIndex[i:end]] + + z = np.dot(batch_X, weights) + h = sigmoid(z) + + error = batch_y - h + gradient = np.dot(batch_X.T, error) / len(batch_y) + gradient -= lambda_reg * weights / len(batch_y) + weights += learning_rate * gradient return weights def predict_logreg(inX, weights): - """ - 对率回归预测函数。 - - Args: - - inX (numpy array): 输入待分类的样本。 - - weights (numpy array): 训练得到的权重。 - - Returns: - - int: 预测的分类标签。 - """ probability = sigmoid(np.dot(inX, weights)) return 1 if probability >= 0.5 else 0 -if __name__ == "__main__": - # 加载训练集 - X_train, y_train = load_data("./data/horse-colic.data") +def load_data(filepath): + data = [] + labels = [] + with open(filepath, 'r') as file: + for line in file: + parts = line.strip().split() + features = parts[:-1] + label = parts[-1] + features = [float(x) if x != '?' else 0.0 for x in features] + data.append(features) + labels.append(1 if label in ['2', '3'] else 0) - # 加载测试集 + # 转换为numpy数组 + data = np.array(data) + labels = np.array(labels) + + # 简单均值归一化 + data_mean = np.mean(data, axis=0) + data_std = np.std(data, axis=0) + data = (data - data_mean) / (data_std + 1e-10) # 防止除零 + + return data, labels + +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=1000) + weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=2000, batch_size=64, lambda_reg=0.01) - # 测试单个数据 - y_pred = predict_logreg(X_test[11], weights) - print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}") + error_count = 0 + for i in range(len(y_test)): + y_pred = predict_logreg(X_test[i], weights) + if y_pred != y_test[i]: + error_count += 1 + print(f"预测结果: {y_pred}, 实际结果: {y_test[i]}") + + accuracy = (len(y_test) - error_count) / len(y_test) + print(f"准确率: {accuracy:.2f}")