diff --git a/function.py b/function.py index d40a072..1ad35a2 100644 --- a/function.py +++ b/function.py @@ -1,7 +1,8 @@ # function.py import numpy as np -import random +import pandas as pd from sklearn.preprocessing import StandardScaler +from sklearn.model_selection import train_test_split, KFold """ 实验说明: @@ -30,30 +31,31 @@ name = "万子玉" def sigmoid(z): return 1 / (1 + np.exp(-z)) -def train_logreg(X, y, learning_rate=0.001, iterations=500, batch_size=16, initial_weights=None): +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) # 添加偏置项 - if initial_weights is None: - weights = np.zeros(X.shape[1]) - else: - weights = initial_weights - - m = X.shape[0] - - for _ in range(iterations): + 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 i in range(0, m, batch_size): - end = i + batch_size - X_batch = X_shuffled[i:end] - y_batch = y_shuffled[i:end] + + 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) - h = sigmoid(z) - gradient = np.dot(X_batch.T, (h - y_batch)) / batch_size + 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 """ @@ -72,8 +74,8 @@ def train_logreg(X, y, learning_rate=0.001, iterations=500, batch_size=16, initi def predict_logreg(inX, weights): inX = np.insert(inX, 0, 1) # 添加偏置项 z = np.dot(inX, weights) - h = sigmoid(z) - return 1 if h >= 0.5 else 0 + prediction_prob = sigmoid(z) + return 1 if prediction_prob >= 0.5 else 0 """ @@ -112,10 +114,10 @@ def split_train_val(X, y, val_size=0.2): 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])] @@ -124,22 +126,22 @@ def load_data(filepath): 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) """ 从文件中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 @@ -156,7 +158,7 @@ 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) y_pred = predict_logreg(X_test[11], weights) print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}") \ No newline at end of file