generated from LufsX/Experiment-LogReg
This commit is contained in:
+44
-99
@@ -1,106 +1,51 @@
|
||||
import os
|
||||
import csv
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.optim as optim
|
||||
from sklearn.model_selection import train_test_split
|
||||
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, roc_auc_score
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
from imblearn.over_sampling import SMOTE
|
||||
|
||||
# 姓名和学号
|
||||
id = 202210423118
|
||||
name = 刘国庆
|
||||
def load_data(filepath):
|
||||
for delimiter in [',', ' ', '\t']:
|
||||
try:
|
||||
data = np.genfromtxt(filepath, delimiter=delimiter, missing_values='?', filling_values=np.nan)
|
||||
if data.ndim < 2 or data.shape[1] < 2:
|
||||
continue
|
||||
data = data[~np.isnan(data).any(axis=1)]
|
||||
if data.size == 0:
|
||||
print(f"Error: No valid data after removing NaN rows in file '{filepath}'.")
|
||||
return None, None
|
||||
X = data[:, :-1]
|
||||
y = data[:, -1]
|
||||
if X.shape[0] != y.shape[0]:
|
||||
print(f"Error: Feature and label count mismatch in file '{filepath}'")
|
||||
return None, None
|
||||
print(f"Loaded data from '{filepath}': {X.shape[0]} samples, {X.shape[1]} features.")
|
||||
return X, y
|
||||
except Exception as e:
|
||||
print(f"Error loading data with delimiter '{delimiter}': {e}")
|
||||
print(f"Error: File '{filepath}' may be empty or improperly formatted.")
|
||||
return None, None
|
||||
|
||||
# 读取 CSV 数据的函数
|
||||
def load_data(file_path):
|
||||
if not os.path.exists(file_path):
|
||||
raise FileNotFoundError(f"文件未找到: {file_path}")
|
||||
|
||||
features = []
|
||||
labels = []
|
||||
with open(file_path, 'r') as csvfile:
|
||||
reader = csv.reader(csvfile)
|
||||
next(reader) # 跳过标题行
|
||||
for row in reader:
|
||||
features.append([float(x) for x in row[:-1]]) # 假设最后一列为标签
|
||||
labels.append(int(row[-1]))
|
||||
return np.array(features), np.array(labels)
|
||||
def sigmoid(z):
|
||||
return 1 / (1 + np.exp(-z))
|
||||
|
||||
# 评估模型的函数
|
||||
def evaluate_model(y_true, y_pred, y_prob=None):
|
||||
print("Confusion Matrix:")
|
||||
print(confusion_matrix(y_true, y_pred))
|
||||
print("\nClassification Report:")
|
||||
print(classification_report(y_true, y_pred))
|
||||
print(f"Accuracy: {accuracy_score(y_true, y_pred):.4f}")
|
||||
|
||||
if y_prob is not None:
|
||||
auc = roc_auc_score(y_true, y_prob)
|
||||
print(f"AUC Score: {auc:.4f}")
|
||||
def train_logreg(X, y, learning_rate=0.01, epochs=1000):
|
||||
X = np.c_[np.ones(X.shape[0]), X]
|
||||
weights = np.zeros(X.shape[1])
|
||||
for epoch in range(epochs):
|
||||
z = np.dot(X, weights)
|
||||
predictions = sigmoid(z)
|
||||
gradient = np.dot(X.T, (predictions - y)) / y.size
|
||||
weights -= learning_rate * gradient
|
||||
return weights
|
||||
|
||||
# 定义模型类
|
||||
class LogisticRegressionModel(nn.Module):
|
||||
def __init__(self, input_size):
|
||||
super(LogisticRegressionModel, self).__init__()
|
||||
self.fc = nn.Linear(input_size, 1)
|
||||
|
||||
def forward(self, x):
|
||||
return torch.sigmoid(self.fc(x))
|
||||
def predict_logreg(X, weights):
|
||||
X = np.c_[np.ones(X.shape[0]), X]
|
||||
probabilities = sigmoid(np.dot(X, weights))
|
||||
return (probabilities >= 0.5).astype(int)
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
# 加载数据
|
||||
file_path = 'data.csv' # 修改为你的 CSV 文件路径
|
||||
X, y = load_data(file_path)
|
||||
|
||||
# 拆分数据集
|
||||
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
|
||||
|
||||
# 处理不平衡数据
|
||||
smote = SMOTE(random_state=42)
|
||||
X_train_res, y_train_res = smote.fit_resample(X_train, y_train)
|
||||
|
||||
# 标准化数据
|
||||
scaler = StandardScaler()
|
||||
X_train_res = scaler.fit_transform(X_train_res)
|
||||
X_test = scaler.transform(X_test)
|
||||
|
||||
# 转换为 PyTorch 张量
|
||||
X_train_res = torch.tensor(X_train_res, dtype=torch.float32)
|
||||
y_train_res = torch.tensor(y_train_res, dtype=torch.float32).view(-1, 1)
|
||||
X_test = torch.tensor(X_test, dtype=torch.float32)
|
||||
y_test = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)
|
||||
|
||||
# 创建模型
|
||||
model = LogisticRegressionModel(input_size=X_train_res.shape[1])
|
||||
|
||||
# 定义损失函数和优化器
|
||||
criterion = nn.BCELoss()
|
||||
optimizer = optim.Adam(model.parameters(), lr=0.001)
|
||||
|
||||
# 训练模型
|
||||
model.train()
|
||||
for epoch in range(100):
|
||||
optimizer.zero_grad() # 清空梯度
|
||||
outputs = model(X_train_res) # 前向传播
|
||||
loss = criterion(outputs, y_train_res) # 计算损失
|
||||
loss.backward() # 反向传播
|
||||
optimizer.step() # 更新权重
|
||||
|
||||
if (epoch + 1) % 10 == 0:
|
||||
print(f'Epoch [{epoch + 1}/100], Loss: {loss.item():.4f}')
|
||||
|
||||
# 评估模型
|
||||
model.eval()
|
||||
with torch.no_grad():
|
||||
y_pred_prob = model(X_test).numpy().flatten() # 获取预测概率
|
||||
y_pred = (y_pred_prob > 0.5).astype(int)
|
||||
|
||||
# 评估模型
|
||||
evaluate_model(y_test.numpy(), y_pred, y_pred_prob)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# Load data and train model
|
||||
data_file_path = 'path_to_your_data/horse-colic.data' # Update with your actual path
|
||||
X, y = load_data(data_file_path)
|
||||
if X is not None and y is not None:
|
||||
weights = train_logreg(X, y)
|
||||
predictions = predict_logreg(X, weights)
|
||||
print("Weights:", weights)
|
||||
print("Predictions:", predictions)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user