浅谈Java设计模式(十三)策略模式(strategy)

策略模式解析
本文介绍策略模式的概念及其在算法决策系统中的应用。通过定义一组可互换的算法并将其封装,使得算法可以在运行时进行选择。文章提供了具体实现案例,包括加法、减法和乘法的实现。

前言:

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下:

图中ICalculator提供同意的方法,
AbstractCalculator是辅助类,提供辅助方法,接下来,依次实现下每个类。

首先统一接口:

public interface ICalculator {  
    public int calculate(String exp);  
}
辅助类:
public abstract class AbstractCalculator {  
      
    public int[] split(String exp,String opt){  
        String array[] = exp.split(opt);  
        int arrayInt[] = new int[2];  
        arrayInt[0] = Integer.parseInt(array[0]);  
        arrayInt[1] = Integer.parseInt(array[1]);  
        return arrayInt;  
    }  
}  
三个实现类:
public class Plus extends AbstractCalculator implements ICalculator {  
  
    @Override  
    public int calculate(String exp) {  
        int arrayInt[] = split(exp,"\\+");  
        return arrayInt[0]+arrayInt[1];  
    }  
}
public class Minus extends AbstractCalculator implements ICalculator {  
  
    @Override  
    public int calculate(String exp) {  
        int arrayInt[] = split(exp,"-");  
        return arrayInt[0]-arrayInt[1];  
    }  
  
}
public class Multiply extends AbstractCalculator implements ICalculator {  
  
    @Override  
    public int calculate(String exp) {  
        int arrayInt[] = split(exp,"\\*");  
        return arrayInt[0]*arrayInt[1];  
    }  
}  

简单的测试类:
public class StrategyTest {  
  
    public static void main(String[] args) {  
        String exp = "2+8";  
        ICalculator cal = new Plus();  
        int result = cal.calculate(exp);  
        System.out.println(result);  
    }  
}  

输出:10

策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。



<think>嗯,用户现在有一个关于调整链接预测任务中训练集和测试集分割比例的问题。他们想比较不同分割比例(60-40、70-30、80-20)下的AUC分数,并生成一个对比表格。首先,我需要理解他们提供的代码和任务要求。 用户提供的代码里,使用了train_test_split来分割数据,其中test_size是0.3,也就是70-30的分割。现在他们需要修改这个比例,测试不同的分割策略。任务提示中提到要找到使用train_test_split的地方并改变比例,然后生成AUC对比表。 首先,我需要确定他们当前的数据结构。xtrain, xtest等是从x和data['link']分割出来的,x可能是特征矩阵,而data['link']是目标变量,即边是否存在。链接预测通常处理的是图的边,所以可能需要更复杂的分割方法,比如按边的比例分割,而不是简单的随机分割。但根据任务描述,用户可能已经将边转换为特征矩阵,所以直接调整train_test_split的test_size参数可能就足够了。 接下来,用户的任务是修改test_size为0.4、0.3、0.2,对应不同的分割比例。然后,对于每个分割比例,训练模型,计算AUC,最后生成比较表格。需要注意的是,分割数据时可能需要保持类别平衡,尤其是链接预测可能存在类别不平衡的问题,正例(存在边)可能比负例少。不过用户代码中已经使用了class_weight="balanced",这可能帮助处理不平衡问题。 在实现步骤上,首先需要循环不同的test_size值,然后分别进行数据分割、模型训练、预测和评估。对于AUC的计算,可能需要使用roc_auc_score函数,同时注意predict_proba返回的是概率,需要选择正类的概率。此外,每次分割需要保持相同的random_state以确保结果的可比性,或者使用不同的随机种子多次运行取平均,但任务中可能只需要一次分割,所以可能固定random_state或者不固定以观察不同情况。 另外,用户提供的代码中使用的是LogisticRegression的predict_proba,这会得到概率估计,计算AUC时需要用到这些概率。需要确认ytest是二进制的标签,0和1,否则可能需要调整。 在生成对比表格时,可以用pandas DataFrame来整理结果,记录不同的test_size和对应的AUC分数,然后展示出来。可能需要考虑多次运行取平均,但根据任务描述,可能直接一次分割即可,所以Deliverable应该是一个简单的表格,包含三种分割比例的AUC值。 需要注意的是,当改变训练集大小时,模型的性能可能会有所变化。较大的训练集可能提高模型性能,但测试集较小可能增加方差。用户可能需要解释结果,比如AUC如何随分割比例变化,是否存在过拟合或欠拟合的情况。 最后,确保代码的正确性,比如正确传递test_size参数,处理random_state是否固定,以及正确计算AUC。此外,可能需要添加必要的库导入,如sklearn的metrics模块。 总结步骤: 1. 修改train_test_split的test_size参数为0.4、0.3、0.2。 2. 对每个test_size,分割数据,训练模型,预测并计算AUC。 3. 汇总结果到表格中,比较不同分割比例的AUC分数。 4. 可能需要进行多次实验或使用交叉验证以获得更可靠的结果,但根据任务提示,可能只需简单比较。 在实现时,可能需要将代码包装在循环中,遍历不同的分割比例,存储每次的AUC,最后生成表格。同时,确保每次分割时数据是重新分割的,避免数据泄漏。另外,如果原始数据的分割没有考虑时间因素或其他图结构特性,可能需要更复杂的分割方法,但根据任务提示,只需调整比例即可。</think>--- ### **分步解决方案:修改链接预测的边分割策略并比较AUC** #### **步骤 1:理解当前代码逻辑** 原代码使用 `train_test_split` 以 **70%-30%** 的比例分割边数据: ```python xtrain, xtest, ytrain, ytest = train_test_split( np.array(x), data['link'], test_size=0.3, random_state=35 ) ``` #### **步骤 2:定义要测试的分割比例** 根据任务要求,需测试以下三种分割策略: - **60%-40%** (`test_size=0.4`) - **70%-30%** (`test_size=0.3`) → 原比例 - **80%-20%** (`test_size=0.2`) --- #### **步骤 3:实现多比例分割与AUC比较** ```python import pandas as pd from sklearn.metrics import roc_auc_score from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression # 定义要测试的分割比例 test_sizes = [0.4, 0.3, 0.2] auc_results = [] for test_size in test_sizes: # 分割数据 xtrain, xtest, ytrain, ytest = train_test_split( np.array(x), data['link'], test_size=test_size, random_state=35 # 固定随机种子保证结果可比性 ) # 训练模型 lr = LogisticRegression(class_weight="balanced") lr.fit(xtrain, ytrain) # 预测概率(取正类的概率) y_proba = lr.predict_proba(xtest)[:, 1] # 计算AUC auc = roc_auc_score(ytest, y_proba) auc_results.append(auc) # 创建对比表格 comparison_df = pd.DataFrame({ "Train-Test Split": [f"{(1-ts)*100:.0f}%-{ts*100:.0f}%" for ts in test_sizes], "AUC Score": auc_results }) print(comparison_df.sort_values(by="AUC Score", ascending=False)) ``` --- ### **步骤 4:结果示例** | Train-Test Split | AUC Score | |-------------------|-----------| | 80%-20% | 0.92 | | 70%-30% | 0.89 | | 60%-40% | 0.85 | --- ### **关键注意事项** 1. **随机种子控制**: - 通过固定 `random_state=35` 确保不同分割比例的数据划分方式一致 - 若需更稳健的结果,可移除 `random_state` 并多次运行取平均 2. **类别不平衡处理**: - 已使用 `class_weight="balanced"` 自动调整类别权重 - 若正负样本极度不平衡,可考虑过采样(SMOTE)或欠采样 3. **模型评估优化**: - 可增加交叉验证 (`StratifiedKFold`) 减少随机性影响 - 若AUC波动大,检查特征工程或尝试其他模型(如随机森林、GNN) --- ### **扩展建议** - **时间敏感分割**:如果是时序图数据,应使用时间窗口分割而非随机分割 - **负采样策略**:链接预测需显式生成不存在的边作为负样本,需确保负样本质量 - **特征工程**:可尝试添加节点中心性特征(如代码1中的度中心性、介数中心性) 通过调整分割比例,可以观察模型在不同数据量下的泛化能力,通常训练数据越多(test_size越小),模型性能会提升,但需警惕过拟合风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值