refactor(PDL): Refactoring the PDL strategy (PR2)#258
Closed
RodionChugunov wants to merge 2 commits into
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PDL Strategy Architecture (PR2)
This document describes the strategy-based refactor of
fedot_ind/core/models/pdl. It explains how the module is structured, how data flows through training and inference, and where to plug in new behavior.What changed in PR2
Before PR2, most PDL logic lived in two large files:
pairwise_core.py— anchors, pair features, pair targets, chunking, aggregationpairwise_model.py— sklearn/FEDOT estimator facadesPR2 splits responsibilities into small, replaceable strategies behind
typing.Protocolcontracts. The public API ofPairwiseDifferenceClassifier,PairwiseDifferenceRegressorandPairwiseDifferenceEstimatoris unchanged.The default behavior for the standard config is also unchanged.
Module map
graph TD %% Основные компоненты (Черные стрелки / Иерархия) pairwise_model --> pairwise_core pairwise_core --> diagnostics pairwise_core --> pair_features pairwise_core --> aggregators pairwise_core --> strategies pairwise_core --> config pairwise_core --> pair_targets %% Функциональные связи (Красные связи) diagnostics -.-> pair_features diagnostics -.-> config pair_features -.-> config aggregators -.-> config aggregators -.-> pair_targets strategies -.-> aggregators strategies -.-> pair_features strategies -.-> config strategies -.-> anchors strategies -.-> contracts strategies -.-> samplers strategies -.-> pair_targets anchors -.-> config anchors -.-> pair_targets %% Стилизация для соответствия оригиналу classDef blackStyle fill:#fff,stroke:#333,stroke-width:1px,color:#000000; classDef redStyle fill:#fff,stroke:#cc0000,stroke-width:1px,color:#cc0000; class pairwise_model,pairwise_core,config,pair_targets blackStyle; class diagnostics,pair_features,aggregators,strategies,anchors,contracts,samplers redStyle; linkStyle 0,1,2,3,4,5,6 stroke:#333,stroke-width:1.5px; linkStyle 7,8,9,10,11,12,13,14,15,16,17,18,19,20 stroke:#cc0000,stroke-width:1.5px;Layering
contracts.pyconfig.py*features/targets/anchors/samplers/aggregators.pystrategies.pypairwise_core.pybuild_pair_batch) and legacy re-exportspairwise_model.pyCore contracts
Classification
0 = same class,1 = different classRegression
target_left - target_anchorpredicted_target = anchor_target + predicted_delta, averaged over anchorsThese contracts are documented in code constants (
CLASSIFICATION_SAME_LABEL, etc.)and exposed at runtime via
diagnostics["pair_target_semantics"].Execution flow
Training (classification)
flowchart TD A[PairwiseDifferenceClassifier.fit] --> B[resolve_pdl_strategies task=classification] B --> C[anchor_selector.select X y] C --> D[build_pair_batch] D --> E[pair_sampler.sample] D --> F[pair_feature_builder.build] D --> G[pair_target_builder.build] D --> H[pair_diagnostics] E --> I[PairwiseBatch] F --> I G --> I H --> I I --> J[base_model.fit batch.features batch.target]Step by step:
PairwiseDifferenceClassifier.__init__callsresolve_pdl_strategies(config, task="classification").fit()encodes labels, thenstrategies_.anchor_selector.select(train_features_, target_encoded_).build_pair_batch(...)composes:AllPairsSampler→ left/anchor index arraysPairFeatureBuilder→ pair feature matrixClassificationDissimilarityTargetBuilder→ dissimilarity targetspair_diagnostics()→ runtime metadata(pair_features, pair_target).Inference (classification)
predict_similarity_by_chunks()builds pair features in chunks and reads P(same) via_predict_same_probability().strategies_.pair_aggregator.aggregate()(MeanSimilarityAggregator) converts the similarity matrix into class probabilities.Training / inference (regression)
Same pattern, but:
RegressionEvenAnchorSelectorRegressionDeltaLeftMinusAnchorTargetBuilderpredict_regression_by_chunks()for inferenceStrategy resolution
Entry point:
strategies.resolve_pdl_strategies(config, task=...).Returns a frozen
PDLStrategiesdataclass:Resolution rules:
classificationClassificationAdaptiveAnchorSelectorClassificationDissimilarityTargetBuilderMeanSimilarityAggregatorregressionRegressionEvenAnchorSelectorRegressionDeltaLeftMinusAnchorTargetBuilderNonepair_feature_modeselects one of:ConcatDiffPairFeatureBuilderConcatAbsdiffPairFeatureBuilderDiffOnlyPairFeatureBuilderAllPairsSampleris currently the only sampler (full cross-product).PR3 guards
Until posterior aggregation is implemented, these configs raise
NotImplementedError:aggregation_policyother thanmean_similarity(classification)symmetric_inference=TrueConfig validation still accepts aliases like
posterior→paper_posterior, butruntime strategy resolution rejects non-default policies explicitly.
Protocol interfaces
Defined in
contracts.py. Concrete classes do not need to inherit from them;they only need matching method signatures (structural subtyping).
PairFeatureBuilderbuild(left, anchors)PairTargetBuilderbuild(y_left, y_anchor)AnchorSelectorselect(X, y)PairSamplersample(n_left, anchor_indices)PairAggregatoraggregate(pair_predictions, anchor_labels, n_classes=...)UncertaintyEstimatorestimate(...)Configuration reference
Key
PairwiseLearningConfigfields:pair_feature_modeconcat_diff, ...)pairing_policymax_pairsanchors_per_classbackendnumpy/torchpair feature backendchunk_sizerandom_stateaggregation_policymean_similarityactive)symmetric_inferenceclass_prior_modeDiagnostics
Every
PairwiseBatchcarries adiagnosticsdict built bypair_diagnostics().Important keys:
n_train,n_anchors,n_pairs,pair_feature_dimanchor_indicesconfig— full normalized config snapshotpair_target_semantics— active mathematical contractEstimator
fit()merges batch diagnostics with task-specific fields(
n_classes,base_model, etc.).Tests
test_pdl_PR2.pytest_pairwise_learning_core.pytest_pdl.pytest_pairwise_difference_models.py