diff --git a/function.py b/function.py index 390a34c..800c7b7 100644 --- a/function.py +++ b/function.py @@ -31,77 +31,88 @@ name = "严锡好" # 这里写自己的代码实现 -# sigmoid函数,用于逻辑回归模型中将线性输出转换为概率 +# Sigmoid函数,用于逻辑回归模型 def sigmoid(z): return 1.0 / (1 + np.exp(-z)) -# compute_gradient函数,用于计算逻辑回归的梯度 +# 计算梯度,用于逻辑回归的梯度下降算法 def compute_gradient(X_batch, y_batch, weights, lambda_reg): - z = np.dot(X_batch, weights) # 计算当前权重下的线性组合 - h = sigmoid(z) # 应用sigmoid函数将线性组合转换为概率 + z = np.dot(X_batch, weights) # 计算z值 + h = sigmoid(z) # 计算sigmoid函数值 gradient = np.dot(X_batch.T, (h - y_batch)) / len(y_batch) # 计算梯度 gradient += (lambda_reg / len(y_batch)) * weights # 添加L2正则化项 return gradient -# train_logreg函数,用于训练逻辑回归模型 +# 训练逻辑回归模型 def train_logreg(X, y, learning_rate=0.001, iterations=10000, batch_size=64, lambda_reg=0.1): m, n = X.shape # 获取样本数量和特征数量 weights = np.random.randn(n) * np.sqrt(2. / n) # 使用He初始化权重 best_weights = weights.copy() # 存储最佳权重 best_accuracy = 0 # 存储最佳准确率 - for i in range(iterations): # 迭代指定次数 + for _ in range(iterations): # 迭代指定次数 indices = np.random.permutation(m) # 随机打乱数据 - X_shuffled = X[indices] - y_shuffled = y[indices] + X_shuffled = X[indices] # 打乱特征 + y_shuffled = y[indices] # 打乱标签 - for j in range(0, m, batch_size): # 批量梯度下降 - X_batch = X_shuffled[j:j + batch_size] - y_batch = y_shuffled[j:j + batch_size] + for j in range(0, m, batch_size): # 按批次处理数据 + X_batch = X_shuffled[j:j + batch_size] # 获取当前批次的特征 + y_batch = y_shuffled[j:j + batch_size] # 获取当前批次的标签 gradient = compute_gradient(X_batch, y_batch, weights, lambda_reg) # 计算梯度 weights -= learning_rate * gradient # 更新权重 - accuracy = accuracy_score(y, predict_logreg(X, weights)) # 计算当前准确率 - if accuracy > best_accuracy: # 更新最佳准确率和最佳权重 - best_accuracy = accuracy + # 计算训练集准确率 + train_accuracy = accuracy(X, y, weights) + if train_accuracy > best_accuracy: # 如果当前准确率更高,则更新最佳权重和准确率 + best_accuracy = train_accuracy best_weights = weights.copy() - if i % 1000 == 0 and accuracy > 0.95: # 动态调整学习率 + # 动态调整学习率 + if _ % 100 == 0 and train_accuracy > 0.95: # 每100次迭代检查一次,如果准确率超过0.95,则减小学习率 learning_rate *= 0.9 return best_weights -# predict_logreg函数,用于使用训练好的权重进行预测 +# 预测函数,用于逻辑回归模型 def predict_logreg(X, weights): - z = np.dot(X, weights) # 计算线性组合 - h = sigmoid(z) # 应用sigmoid函数 + z = np.dot(X, weights) # 计算z值 + h = sigmoid(z) # 计算sigmoid函数值 return np.where(h >= 0.5, 1, 0) # 返回预测结果 -# preprocess_data函数,用于预处理数据 -def preprocess_data(X, y): - y[y == 2] = 0 # 将类别2转换为0 - y[y == 3] = 0 # 将类别3转换为0 - X = np.delete(X, [3], axis=1) # 删除特征3 - X = X[:, :23] # 删除特征24~28 - return X, y - -# load_data函数,用于加载数据 +# 加载数据函数 def load_data(filepath): - try: - data = pd.read_csv(filepath, header=None, sep=r'\s+', on_bad_lines='skip') # 读取数据 - except pd.errors.ParserError as e: - print(f"Error parsing file: {e}") - return None, None - data.replace('?', np.nan, inplace=True) # 将'?'替换为np.nan - imputer = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0) # 填充缺失值 - data.iloc[:, :-1] = imputer.fit_transform(data.iloc[:, :-1]) - for col in data.columns[:-1]: - data[col] = pd.to_numeric(data[col], errors='coerce') # 转换为数值类型 - X = data.iloc[:, :-1].values # 特征数据 - y = data.iloc[:, -1].values.astype(int) # 目标变量 - X, y = preprocess_data(X, y) # 预处理数据 - return X, y + data, labels = [], [] + with open(filepath, 'r') as f: # 打开文件 + for line in f: # 逐行读取 + line = line.strip().split() # 去除空格并分割 + if len(line) >= 1 and line[-1].isdigit(): # 确保行数据有效 + line_data = [0 if x == '?' else float(x) for x in line[:-1]] # 将非数字替换为0并转换为浮点数 + data.append(line_data) + labels.append(int(line[-1])) # 将标签转换为整数 + data = np.array(data) # 转换为numpy数组 + labels = np.array(labels) + + # 检查特征数量并进行特征选择 + num_features = data.shape[1] + indices_to_delete = [2] # 特征3 + if num_features > 24: # 确保特征数量足够 + indices_to_delete += list(range(24, 27)) # 特征24到27 + + # 删除特征 + data = np.delete(data, indices_to_delete, axis=1) + + # 将标签二分类化 + target_variable = np.where((labels == 2) | (labels == 3), 0, 1) + + return data, target_variable + +# 计算准确率函数 +def accuracy(X, y, weights): + predictions = predict_logreg(X, weights) # 预测结果 + return np.mean(predictions == y) # 计算准确率 + +# 主函数 if __name__ == "__main__": # 加载数据 X, y = load_data("./data/horse-colic.data") @@ -118,8 +129,7 @@ if __name__ == "__main__": final_weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=5000, batch_size=64, lambda_reg=0.1) # 验证模型 - y_pred = predict_logreg(X_val, final_weights) - val_accuracy = accuracy_score(y_val, y_pred) + val_accuracy = accuracy(X_val, y_val, final_weights) print(f"验证集的准确率: {val_accuracy:.4f}") # 加载测试集 @@ -127,6 +137,5 @@ if __name__ == "__main__": X_test = scaler.transform(X_test) # 测试模型 - y_test_pred = predict_logreg(X_test, final_weights) - test_accuracy = accuracy_score(y_test, y_test_pred) - print(f"最终测试集的准确率: {test_accuracy:.4f}") \ No newline at end of file + final_test_accuracy = accuracy(X_test, y_test, final_weights) + print(f"最终测试集的准确率: {final_test_accuracy:.4f}") \ No newline at end of file