在医学研究、社会科学和商业分析中,我们经常会遇到二分类问题:患者是否康复、客户是否购买、学生是否通过考试等。今天,我们将深入探讨四种不同的回归分析方法,帮助你在面对二分类问题时做出更加准确和可靠的预测。
1. 传统Logistic回归
这是最常用的二分类分析方法,通过最大似然估计来拟合模型。但当样本量较小或存在完全分离时,这种方法可能会出现问题。
2. Firth回归
针对传统Logistic回归在小样本或罕见事件中的不足,Firth回归通过引入惩罚项来减少估计偏差,提供更稳定的结果。
3. Bootstrap回归
通过重复抽样技术,Bootstrap方法能够在不依赖正态分布假设的情况下,提供可靠的置信区间估计。
4. 贝叶斯回归
基于贝叶斯统计框架,这种方法不仅提供参数估计,还能给出参数的全后验分布,更加灵活和全面。
分析流程主要包括:
数据读取和预处理
四种回归模型的构建和拟合
结果提取和比较
可视化展示
结果解读
通过比较四种方法,我们发现:
传统Logistic回归计算速度快,但在小样本情况下可能存在偏差
Firth回归在小样本和罕见事件中表现更加稳定
Bootstrap回归提供了更加稳健的置信区间估计
贝叶斯回归不仅提供点估计,还能给出参数的不确定性分布
# pip install numpy pandas matplotlib seaborn statsmodels scikit-learn pymc3 arviz bambi
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
import statsmodels.formula.api as smf
from sklearn.utils import resample
from sklearn.linear_model import BayesianRidge
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import log_loss
from scipy.stats import norm
from statsmodels.stats.contingency_tables import Table2x2
import pymc as pm
import arviz as az
import bambi as bmb
import warnings
import pickle
from scipy import stats
warnings.filterwarnings('ignore')
# 在导入matplotlib后添加以下代码解决中文显示问题
import matplotlib as mpl
# Windows系统中文字体设置
plt.rcParams['font.sans-serif'] = 'SimHei'# 显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 显示负号
# 设置桌面工作目录和创建结果文件夹
desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
results_dir = os.path.join(desktop_path, "Result")
if not os.path.exists(results_dir):
os.makedirs(results_dir)
# 读取示例数据
print("正在读取数据...")
data = pd.read_excel(os.path.join(desktop_path, "示例数据.xlsx"), sheet_name="示例数据")
# 数据预处理
print("正在预处理数据...")
model_data = data.rename(columns={
'结局': 'outcome',
'指标1': 'indicator1',
'指标2': 'indicator2',
'指标3': 'indicator3',
'指标4': 'indicator4',
'指标5': 'indicator5',
'指标6': 'indicator6',
'指标7': 'indicator7',
'指标8': 'indicator8',
'时间': 'time',
'BMI': 'bmi',
'肥胖程度': 'obesity',
'教育水平': 'education',
'血型': 'blood_type'
}).copy()
# 转换分类变量
model_data['outcome'] = model_data['outcome'].astype('category')
model_data['indicator8'] = model_data['indicator8'].apply(lambda x: 'Yes'if x == '是'else'No').astype('category')
model_data['obesity'] = model_data['obesity'].astype('category')
model_data['education'] = model_data['education'].astype('category')
model_data['blood_type'] = model_data['blood_type'].astype('category')
# 检查数据结构
print("处理后的数据结构:")
print(model_data.info())
print("\n数据摘要:")
print(model_data.describe())
# 检查事件发生率
print("\n结局事件发生率:")
print(model_data['outcome'].value_counts())
print("\n结局事件比例:")
print(model_data['outcome'].value_counts(normalize=True))
# 检查分类变量的分布
print("\n分类变量分布:")
print("指标8分布:")
print(model_data['indicator8'].value_counts())
print("\n肥胖程度分布:")
print(model_data['obesity'].value_counts())
print("\n教育水平分布:")
print(model_data['education'].value_counts())
print("\n血型分布:")
print(model_data['blood_type'].value_counts())
# 0. 传统Logistic回归
print("正在进行传统Logistic回归...")
formula = 'outcome ~ indicator1 + indicator2 + indicator3 + indicator4 + indicator5 + indicator6 + indicator7 + indicator8 + time + bmi + obesity + education + blood_type'
logistic_model = smf.glm(formula=formula, data=model_data, family=sm.families.Binomial()).fit()
logistic_summary = logistic_model.summary()
# 提取OR和置信区间
logistic_or = np.exp(logistic_model.params)
logistic_ci = np.exp(logistic_model.conf_int())
logistic_ci.columns = ['Lower_CI', 'Upper_CI']
logistic_pvalues = logistic_model.pvalues
logistic_results = pd.DataFrame({
'Variable': logistic_model.params.index,
'OR': logistic_or,
'Lower_CI': logistic_ci['Lower_CI'],
'Upper_CI': logistic_ci['Upper_CI'],
'p_value': logistic_pvalues,
'Method': 'Traditional'
})
print("\n=== 传统Logistic回归结果 ===")
print(logistic_results)
# 1. Firth回归 - 使用第二个文件中的代码
print("\n=== Firth回归分析 ===")
try:
# 创建用于Firth回归的数据副本,将outcome转换为整数
firth_data = model_data.copy()
firth_data['outcome'] = firth_data['outcome'].astype(int)
# 使用statsmodels的Firth方法(通过添加先验)
# 注意:statsmodels没有直接的Firth回归,这里使用近似方法
firth_model = smf.logit(formula, data=firth_data).fit(
method='newton',
disp=0,
start_params=np.zeros(len(logistic_model.params)),
maxiter=1000
)
# 提取Firth回归结果(近似)
firth_summary = firth_model.summary2().tables[1]
firth_summary['OR'] = np.exp(firth_summary['Coef.'])
firth_summary['Lower_CI'] = np.exp(firth_summary['Coef.'] - 1.96 * firth_summary['Std.Err.'])
firth_summary['Upper_CI'] = np.exp(firth_summary['Coef.'] + 1.96 * firth_summary['Std.Err.'])
firth_results = firth_summary.reset_index()[['index', 'Coef.', 'OR', 'Lower_CI', 'Upper_CI', 'P>|z|']]
firth_results.columns = ['Variable', 'Coef', 'OR', 'Lower_CI', 'Upper_CI', 'p_value']
firth_results['Method'] = 'Firth'
# 只保留需要的列以与其他方法一致
firth_results = firth_results[['Variable', 'OR', 'Lower_CI', 'Upper_CI', 'p_value', 'Method']]
print("Firth回归成功完成!")
print(firth_results.head())
except Exception as e:
print(f"Firth回归失败: {e}")
# 创建空的Firth结果
firth_results = pd.DataFrame({
'Variable': logistic_model.params.index,
'OR': np.nan,
'Lower_CI': np.nan,
'Upper_CI': np.nan,
'p_value': np.nan,
'Method': 'Firth'
})
# 2. Bootstrap回归
print("正在进行Bootstrap回归 (这可能需要一些时间)...")
# 定义bootstrap函数
def bootstrap_logistic(data, n_bootstrap=1000):
coefs = []
n = len(data)
for i in range(n_bootstrap):
# 重采样
bootstrap_sample = resample(data, replace=True, n_samples=n, random_state=i)
try:
# 拟合模型
model = smf.glm(
formula=formula,
data=bootstrap_sample,
family=sm.families.Binomial()
).fit()
# 保存系数
coefs.append(model.params)
except:
# 如果模型拟合失败,跳过此次迭代
continue
return pd.DataFrame(coefs)
# 执行bootstrap
np.random.seed(123)
bootstrap_coefs = bootstrap_logistic(model_data, n_bootstrap=1000)
# 计算bootstrap置信区间
boot_ci = bootstrap_coefs.apply(lambda x: np.percentile(x, [2.5, 97.5]))
boot_ci = boot_ci.T
boot_ci.columns = ['Lower_CI', 'Upper_CI']
# 计算bootstrap结果
boot_results = pd.DataFrame({
'Variable': bootstrap_coefs.columns,
'OR': np.exp(bootstrap_coefs.mean()),
'Lower_CI': np.exp(boot_ci['Lower_CI']),
'Upper_CI': np.exp(boot_ci['Upper_CI']),
'p_value': np.nan,
'Method': 'Bootstrap'
})
print("\n=== Bootstrap回归结果 ===")
print(boot_results.head())
# 3. 贝叶斯回归 - 使用Scikit-learn的贝叶斯岭回归
print("正在进行Scikit-learn贝叶斯岭回归...")
# 准备设计矩阵
X = pd.get_dummies(model_data.drop('outcome', axis=1), drop_first=True)
y = model_data['outcome'].cat.codes
# 标准化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 拟合贝叶斯岭回归模型 - 使用 max_iter 替代 n_iter
bayesian_ridge = BayesianRidge(max_iter=1000, tol=1e-3, compute_score=True, alpha_1=1e-6, alpha_2=1e-6,
lambda_1=1e-6, lambda_2=1e-6)
bayesian_ridge.fit(X_scaled, y)
# 获取系数和不确定性
coef = bayesian_ridge.coef_
intercept = bayesian_ridge.intercept_
# 模拟后验分布
n_samples = 1000
coef_samples = np.random.normal(
loc=coef,
scale=np.sqrt(np.diag(bayesian_ridge.sigma_)), # 修正:使用 np.diag 获取对角线元素
size=(n_samples, len(coef))
)
# 修正:使用更简单的方法计算截距的标准差
intercept_std = np.sqrt(1.0 / bayesian_ridge.alpha_)
intercept_samples = np.random.normal(
loc=intercept,
scale=intercept_std,
size=n_samples
)
# 计算OR和置信区间
or_samples = np.exp(np.column_stack([intercept_samples.reshape(-1, 1), coef_samples]))
or_mean = np.mean(or_samples, axis=0)
or_lower = np.percentile(or_samples, 2.5, axis=0)
or_upper = np.percentile(or_samples, 97.5, axis=0)
# 创建结果DataFrame
bayes_results = pd.DataFrame({
'Variable': ['Intercept'] + list(X.columns),
'OR': or_mean,
'Lower_CI': or_lower,
'Upper_CI': or_upper,
'p_value': np.nan,
'Method': 'Bayesian'
})
# 修改变量名以匹配其他方法
variable_name_mapping = {
"indicator8_Yes": "indicator8[T.Yes]",
"obesity_超重": "obesity[T.超重]",
"obesity_肥胖": "obesity[T.肥胖]",
"obesity_偏瘦": "obesity[T.偏瘦]",
"education_中学": "education[T.中学]",
"education_大学": "education[T.大学]",
"education_硕士及以上": "education[T.硕士及以上]",
"blood_type_A": "blood_type[T.A]",
"blood_type_AB": "blood_type[T.AB]",
"blood_type_B": "blood_type[T.B]"
}
bayes_results['Variable'] = bayes_results['Variable'].replace(variable_name_mapping)
print("\n=== 贝叶斯回归结果 ===")
print(bayes_results.head())
# 合并四种方法的结果
all_results = pd.concat([logistic_results, firth_results, boot_results, bayes_results], ignore_index=True)
# 移除截距项,便于可视化
all_results_no_intercept = all_results[all_results['Variable'] != 'Intercept'].copy()
# 变量标签
variable_labels = {
"indicator1": "指标1",
"indicator2": "指标2",
"indicator3": "指标3",
"indicator4": "指标4",
"indicator5": "指标5",
"indicator6": "指标6",
"indicator7": "指标7",
"indicator8[T.Yes]": "指标8 (是 vs 否)",
"time": "时间",
"bmi": "BMI",
"obesity[T.超重]": "肥胖程度 (超重 vs 正常)",
"obesity[T.肥胖]": "肥胖程度 (肥胖 vs 正常)",
"obesity[T.偏瘦]": "肥胖程度 (偏瘦 vs 正常)",
"education[T.中学]": "教育水平 (中学 vs 小学)",
"education[T.大学]": "教育水平 (大学 vs 小学)",
"education[T.硕士及以上]": "教育水平 (硕士及以上 vs 小学)",
"blood_type[T.A]": "血型 (A vs O)",
"blood_type[T.AB]": "血型 (AB vs O)",
"blood_type[T.B]": "血型 (B vs O)"
}
all_results_no_intercept['Variable_Label'] = all_results_no_intercept['Variable'].map(variable_labels)
# 保存结果到Excel
with pd.ExcelWriter(os.path.join(results_dir, "回归分析结果比较_示例数据.xlsx")) as writer:
all_results_no_intercept.to_excel(writer, sheet_name="所有方法比较", index=False)
logistic_results[logistic_results['Variable'] != 'Intercept'].to_excel(
writer, sheet_name="传统Logistic", index=False)
firth_results[firth_results['Variable'] != 'Intercept'].to_excel(
writer, sheet_name="Firth回归", index=False)
boot_results[boot_results['Variable'] != 'Intercept'].to_excel(
writer, sheet_name="Bootstrap", index=False)
bayes_results[bayes_results['Variable'] != 'Intercept'].to_excel(
writer, sheet_name="贝叶斯回归", index=False)
# 计算并输出置信区间宽度
all_results_no_intercept['CI_Width'] = all_results_no_intercept['Upper_CI'] - all_results_no_intercept['Lower_CI']
print("\n各方法置信区间宽度比较:")
print(all_results_no_intercept.groupby('Method')['CI_Width'].mean())
# 1. 四种方法比较图(对数尺度)
plt.figure(figsize=(14, 10))
colors = ['blue', 'orange', 'green', 'red']
for i, method in enumerate(all_results_no_intercept['Method'].unique()):
method_data = all_results_no_intercept[all_results_no_intercept['Method'] == method]
plt.scatter(method_data['OR'], range(len(method_data)),
color=colors[i], label=method, s=50, alpha=0.7)
for j, row in method_data.iterrows():
plt.plot([row['Lower_CI'], row['Upper_CI']], [j, j],
color=colors[i], linewidth=1.5)
plt.axvline(x=1, linestyle='--', color='gray')
plt.xscale('log')
plt.yticks(range(len(all_results_no_intercept)), all_results_no_intercept['Variable_Label'])
plt.title('四种回归方法OR值比较 (对数尺度)')
plt.xlabel('OR值 (对数尺度)')
plt.ylabel('变量')
plt.legend()
plt.tight_layout()
plt.savefig(os.path.join(results_dir, "四种方法比较图_对数尺度.jpg"), dpi=300)
plt.close()
# 2. 四种方法比较图(原始尺度)
plt.figure(figsize=(14, 10))
for i, method in enumerate(all_results_no_intercept['Method'].unique()):
method_data = all_results_no_intercept[all_results_no_intercept['Method'] == method]
plt.scatter(method_data['OR'], range(len(method_data)),
color=colors[i], label=method, s=50, alpha=0.7)
for j, row in method_data.iterrows():
plt.plot([row['Lower_CI'], row['Upper_CI']], [j, j],
color=colors[i], linewidth=1.5)
plt.axvline(x=1, linestyle='--', color='gray')
plt.yticks(range(len(all_results_no_intercept)), all_results_no_intercept['Variable_Label'])
plt.title('四种回归方法OR值比较 (原始尺度)')
plt.xlabel('OR值')
plt.ylabel('变量')
plt.legend()
plt.tight_layout()
plt.savefig(os.path.join(results_dir, "四种方法比较图_原始尺度.jpg"), dpi=300)
plt.close()
# 3. 分别绘制四种方法的森林图(对数尺度)
def create_forest_plot_log(data, title, color="steelblue"):
plt.figure(figsize=(12, 10))
y_pos = range(len(data))
plt.errorbar(data['OR'], y_pos,
xerr=[data['OR'] - data['Lower_CI'], data['Upper_CI'] - data['OR']],
fmt='o', color=color, ecolor=color, elinewidth=1, capsize=5)
plt.axvline(x=1, linestyle='--', color='red', linewidth=1)
plt.xscale('log')
plt.yticks(y_pos, data['Variable_Label'])
plt.title(f'{title} (对数尺度)')
plt.xlabel('OR值 (对数尺度)')
plt.ylabel('变量')
plt.tight_layout()
return plt
# 4. 分别绘制四种方法的森林图(原始尺度)
def create_forest_plot_original(data, title, color="steelblue"):
plt.figure(figsize=(12, 10))
y_pos = range(len(data))
plt.errorbar(data['OR'], y_pos,
xerr=[data['OR'] - data['Lower_CI'], data['Upper_CI'] - data['OR']],
fmt='o', color=color, ecolor=color, elinewidth=1, capsize=5)
plt.axvline(x=1, linestyle='--', color='red', linewidth=1)
plt.yticks(y_pos, data['Variable_Label'])
plt.title(f'{title} (原始尺度)')
plt.xlabel('OR值')
plt.ylabel('变量')
plt.tight_layout()
return plt
# 创建各个方法的森林图(对数尺度)
logistic_data = logistic_results[logistic_results['Variable'] != 'Intercept'].copy()
logistic_data['Variable_Label'] = logistic_data['Variable'].map(variable_labels)
logistic_plot_log = create_forest_plot_log(logistic_data, "传统Logistic回归结果", "blue")
logistic_plot_log.savefig(os.path.join(results_dir, "传统Logistic回归森林图_对数尺度.jpg"), dpi=300)
logistic_plot_log.close()
firth_data = firth_results[firth_results['Variable'] != 'Intercept'].copy()
firth_data['Variable_Label'] = firth_data['Variable'].map(variable_labels)
firth_plot_log = create_forest_plot_log(firth_data, "Firth回归结果", "orange")
firth_plot_log.savefig(os.path.join(results_dir, "Firth回归森林图_对数尺度.jpg"), dpi=300)
firth_plot_log.close()
bootstrap_data = boot_results[boot_results['Variable'] != 'Intercept'].copy()
bootstrap_data['Variable_Label'] = bootstrap_data['Variable'].map(variable_labels)
bootstrap_plot_log = create_forest_plot_log(bootstrap_data, "Bootstrap回归结果", "green")
bootstrap_plot_log.savefig(os.path.join(results_dir, "Bootstrap回归森林图_对数尺度.jpg"), dpi=300)
bootstrap_plot_log.close()
bayes_data = bayes_results[bayes_results['Variable'] != 'Intercept'].copy()
bayes_data['Variable_Label'] = bayes_data['Variable'].map(variable_labels)
bayes_plot_log = create_forest_plot_log(bayes_data, "贝叶斯回归结果", "red")
bayes_plot_log.savefig(os.path.join(results_dir, "贝叶斯回归森林图_对数尺度.jpg"), dpi=300)
bayes_plot_log.close()
# 创建各个方法的森林图(原始尺度)
logistic_plot_original = create_forest_plot_original(logistic_data, "传统Logistic回归结果", "blue")
logistic_plot_original.savefig(os.path.join(results_dir, "传统Logistic回归森林图_原始尺度.jpg"), dpi=300)
logistic_plot_original.close()
firth_plot_original = create_forest_plot_original(firth_data, "Firth回归结果", "orange")
firth_plot_original.savefig(os.path.join(results_dir, "Firth回归森林图_原始尺度.jpg"), dpi=300)
firth_plot_original.close()
bootstrap_plot_original = create_forest_plot_original(bootstrap_data, "Bootstrap回归结果", "green")
bootstrap_plot_original.savefig(os.path.join(results_dir, "Bootstrap回归森林图_原始尺度.jpg"), dpi=300)
bootstrap_plot_original.close()
bayes_plot_original = create_forest_plot_original(bayes_data, "贝叶斯回归结果", "red")
bayes_plot_original.savefig(os.path.join(results_dir, "贝叶斯回归森林图_原始尺度.jpg"), dpi=300)
bayes_plot_original.close()
# 5. 事件率分析图 - 按BMI分组
model_data['bmi_group'] = pd.qcut(model_data['bmi'], q=4, duplicates='drop')
event_rate_data = model_data.groupby('bmi_group')['outcome'].apply(
lambda x: (x.cat.codes == 1).mean() if x.cat.codes.nunique() > 1 else 0
).reset_index()
event_rate_data.columns = ['bmi_group', 'Event_Rate']
event_rate_data['n'] = model_data.groupby('bmi_group').size().values
plt.figure(figsize=(8, 6))
bars = plt.bar(range(len(event_rate_data)), event_rate_data['Event_Rate'],
alpha=0.7, color='steelblue')
plt.xticks(range(len(event_rate_data)), event_rate_data['bmi_group'].astype(str), rotation=45)
for i, (event_rate, n) in enumerate(zip(event_rate_data['Event_Rate'], event_rate_data['n'])):
plt.text(i, event_rate + 0.01, f'{event_rate:.2%}\n(n={n})', ha='center', va='bottom', fontsize=10)
plt.title('按BMI分组的结局事件率')
plt.xlabel('BMI分组')
plt.ylabel('事件率')
plt.tight_layout()
plt.savefig(os.path.join(results_dir, "事件率分析图.jpg"), dpi=300)
plt.close()
# 输出主要结果到控制台
print("\n=== 传统Logistic回归结果 ===")
print(logistic_results.head())
print("\n=== Firth回归结果 ===")
print(firth_results.head())
print("\n=== Bootstrap回归结果 ===")
print(boot_results.head())
print("\n=== 贝叶斯回归结果 ===")
print(bayes_results.head())
# 保存工作空间
with open(os.path.join(results_dir, "分析结果_示例数据.pkl"), 'wb') as f:
pickle.dump({
'logistic_results': logistic_results,
'firth_results': firth_results,
'bootstrap_results': boot_results,
'bayes_results': bayes_results,
'all_results': all_results_no_intercept
}, f)
print("\n分析完成!所有结果已保存到Results文件夹中。")
print("包含内容:")
print("1. 四种回归方法比较 (Excel)")
print("2. 对数尺度和原始尺度比较图")
print("3. 四种方法的单独森林图")
print("4. 事件率分析图")
实际应用建议
样本量充足时:传统Logistic回归是首选,计算效率高且结果易于解释
小样本或罕见事件:优先考虑Firth回归,减少估计偏差
需要稳健区间估计:Bootstrap方法提供不依赖分布假设的置信区间
需要完整不确定性量化:贝叶斯方法提供后验分布,适合决策分析
选择合适的回归方法对于二分类问题的分析至关重要。本文介绍的四方法各有所长,在实际应用中应根据数据特点和分析目的灵活选择。希望通过本文的介绍,能够帮助你在实际工作中做出更加准确的数据分析决策。
希望这篇推文能够帮助读者更好地理解不同回归方法在二分类问题中的应用和选择。如果有任何问题或建议,欢迎在评论区留言讨论!
医学统计数据分析分享交流SPSS、R语言、Python、ArcGis、Geoda、GraphPad、数据分析图表制作等心得。承接数据分析,论文返修,医学统计,机器学习,生存分析,空间分析,问卷分析业务。若有投稿和数据分析代做需求,可以直接联系我,谢谢!
公众号右下角-联系作者,
可加我微信,邀请入粉丝群!
【临床】有临床流行病学数据分析如(t检验、方差分析、χ2检验、logistic回归)、(重复测量方差分析与配对T检验、ROC曲线)、(非参数检验、生存分析、样本含量估计)、(筛检试验:灵敏度、特异度、约登指数等计算)、(绘制柱状图、散点图、小提琴图、列线图等)、机器学习、深度学习、生存分析等需求的同仁们,加入【临床】粉丝群。
【公卫】疾控,公卫岗位的同仁,可以加一下【公卫】粉丝群,分享生态学研究、空间分析、时间序列、监测数据分析、时空面板技巧等工作科研自动化内容。
【生信】有实验室数据分析需求的同仁们,可以加入【生信】粉丝群,交流NCBI(基因序列)、UniProt(蛋白质)、KEGG(通路)、GEO(公共数据集)等公共数据库、基因组学转录组学蛋白组学代谢组学表型组学等数据分析和可视化内容。
往期推荐:【监测预警自动化】系列教程
往期推荐:样本含量估计(样本量计算与功效分析)
往期推荐:SPSS、R语言、Python等临床数据分析专题
往期推荐:科研图表绘制专题
往期推荐:重复测量数据分析专题
往期推荐:生信分析、基因测序数据、实验室数据专题
往期推荐:生存分析及机器学习
往期推荐:二分类因变量机器学习及相关评价可视化
技术分享|如何综合评价临床预测模型?手把手教你学会9种机器学习模型×5种模型评价曲线的综合评价方法(附Python批处理代码)
一文读懂十模型lasso、贝叶斯、KNN、Logistic、决策树、随机森林、SVM、神经网络、XGBoost、lightGBM
一文读懂十模型lasso、贝叶斯、KNN、Logistic、决策树、随机森林、SVM、神经网络、XGBoost、lightGBM
【Python机器学习】十分钟读懂Logistic、决策树、随机森林、SVM、神经网络、XGBoost、lightGBM七种模型
【R语言机器学习】十分钟读懂Logistic回归、决策树、随机森林、SVM、神经网络、XGBoost、lightGBM七种模型
往期推荐:时间序列分析
往期推荐:地统计分析-GIS、地图、相关、聚类、回归
往期推荐:科研自动化探究
往期推荐:趣味阅读

