sensor_selection

Module: missions.nodes.spatial_filtering.sensor_selection

Methods for sensor selection optimization algorithms

Note

The words sensor and channel are used as synonyms.

Inheritance diagram for pySPACE.missions.nodes.spatial_filtering.sensor_selection:

Inheritance diagram of pySPACE.missions.nodes.spatial_filtering.sensor_selection

Class Summary

SensorSelectionBase([num_selected_sensors, ...]) Template for nodes that select sensors
SensorSelectionRankingNode(ranking_spec, ranking) Iteratively choose sensors depending on a ranking function
SensorSelectionSSNRNode(num_selected_sensors) Select sensors based on maximizing the SSNR
PerformanceRanker(ranking_spec) Rank sensors by performance after evaluating classification flows
RemoveOnePerformanceRanker(\*\*kwargs) Rank sensors by evaluating if classification performance drops without them
AddOnePerformanceRanker(\*\*kwargs) Rank sensors by evaluating performance increase on usage
CoefficientRanker(ranking_spec, run_number) Get a ranking from the second last processing node
EvolutionaryAlgorithm(total_elements, ...) Black-box optimization using an evolutionary algorithm
RecursiveBackwardElimination(total_elements) Black-box optimization using recursive backward elimination

Function Summary

evaluate_sensor_selection(cns, flow, metric, ...) Execute the evaluation flow

Classes

SensorSelectionBase

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.SensorSelectionBase(num_selected_sensors=2, store=True, **kwargs)[source]

Bases: pySPACE.missions.nodes.base_node.BaseNode

Template for nodes that select sensors

This node implements the basic framework for nodes that select sensors. The train method has to be overwritten as it is the place for the specific selection procedures and criteria.

Parameters
num_selected_sensors:
 

Determines how many sensors are kept.

(optional, default: 2)

store:

In contrary to the base node, the default of this node is to store the chosen sensors and rankings.

If the store parameter is set to True, one file named “sensor_selection.txt” will be saved. This text file holds the list of chosen sensors with no particular order. If the SensorSelectionRankingNode is used, another file called “ordered_list_of_picks.txt” will be saved. This is an ordered list of the picks that were made due to the ranking. E.g., in a “remove_1” setting, the first sensor in the list is the first that was removed. In a “add_1” setting it is the first one that was added. Additionally, one file called “sensor_ranking.txt” will be created. This file is a merge of the aforementioned. The first entries are the selected channels that can’t be ranked in alphabetical order. Then come the (de-)selected sensors in order of descending relevance.

(optional, default: True)

The following shows a complete example using the SensorSelectionRankingNode to illustrate, how nodes of this type can be used. In this case, the number of sensors is first reduced to 8 removing 2 sensors at a time, than increased back to 16 adding 4 at a time.

Exemplary Call

- 
    node : Time_Series_Source
-
    node : CV_Splitter
-
    node : FFT_Band_Pass_Filter
    parameters : 
            pass_band : [0.0, 4.0]
            keep_in_history : True
-
    node : Sensor_Selection_Ranking
    parameters :
        ranking : Remove_One_Performance_Ranking
        num_selected_sensors : 8
        recast_method : remove_2
        ranking_spec :
            pool_size : 2
            std_weight : 1
            flow :
                -
                    node : CV_Splitter
                -
                    node : Time_Domain_Features
                -
                    node : 2SVM
                -
                    node : Classification_Performance_Sink
-
    node : Sensor_Selection_Ranking
    parameters :
        ranking : Add_One_Performance_Ranking
        num_selected_sensors : 16
        recast_method : add_4
        store : True
        ranking_spec :
            std_weight : 1
            pool_size : 2
            flow :
                -
                    node : CV_Splitter
                -
                    node : Time_Domain_Features
                -
                    node : 2SVM
                -
                    node : Classification_Performance_Sink
-
    node : Time_Domain_Features
-
    node : 2SVM
-
    node : Classification_Performance_Sink
Author:Mario Krell & David Feess 2011/09/23
Created:2011/09/23

Class Components Summary

_execute(data) Project the data onto the selected channels.
_train(data, label) This method has to be overwritten by the different sensor selection nodes
is_supervised() Returns whether this node requires supervised training
is_trainable() Returns whether this node is trainable.
store_state(result_dir[, index]) Store the names of the selected sensors into result_dir
__init__(num_selected_sensors=2, store=True, **kwargs)[source]
is_trainable()[source]

Returns whether this node is trainable.

is_supervised()[source]

Returns whether this node requires supervised training

_train(data, label)[source]

This method has to be overwritten by the different sensor selection nodes

_execute(data)[source]

Project the data onto the selected channels.

store_state(result_dir, index=None)[source]

Store the names of the selected sensors into result_dir

SensorSelectionRankingNode

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.SensorSelectionRankingNode(ranking_spec, ranking, recast_method='remove_1', **kwargs)[source]

Bases: pySPACE.missions.nodes.spatial_filtering.sensor_selection.SensorSelectionBase

Iteratively choose sensors depending on a ranking function

This node collects the training data and generates a ranker. Then it evaluates different sub-/supersets of the current set of sensors using this ranker, and dismisses or adds sensors according to the ranking result.

The ranking function can (and often will) in fact consist of the evaluation of an entire classification flow. After that, e.g., achieved performance or the values of certain classifier parameters can be used as ranking. See the PerformanceRanker and CoefficientRanker classes for details.

Note

The code of this node is partly copied from parameter optimization node.

Parameters
num_selected_sensors:
 

Determines how many sensors are kept.

ranking:

String specifying the desired method for the ranking of sensors. The string must be known to the create_ranker method. So far implemented:

  • “Remove_One_Performance_Ranking”
    Based on the current set of sensors, the ranking of one sensor is computed by removing it and evaluating the performance based on the remaining sensors. The classification node chain has to be specified. One would typically use this together with a “remove_*” ranking_spec (see below) to implement a “recursive backwards elimination”.
  • “Add_One_Performance_Ranking”
    This Ranker takes the current set as fixed and extends it by previously dismissed sensors. This implementation gains access to the previously dismissed channels through the data.history. Thus, in order for this to work, make sure that a previous node in the flow (that works on a larger set of sensors) has set “keep_in_history : True”. See the example flow in the documentation of SensorSelectionBase. The current set of sensors plus one of the dismissed sensors will be evaluated. This will be repeated for each of the previously dismissed sensors. The ranking results from the classification performance. One would typically use this together with a “add_n” ranking_spec to re-add the n best performing sensors.
  • “Coefficient_Ranking”
    performs a classification flow (which has to be specified in ranking_spec) using all currently active sensors. The actual ranking is then provided by the classifier’s get_sensor_ranking method.
ranking_spec:

Arguments passed to the ranker upon creation. Often contains a classification flow of some sort.

recast_method:

Determines how the set of sensors is altered based on the ranking. Most commonly, the worst sensor will be removed until the desired number of sensors is reached. Alternatively, n sensors at a time could be removed. When using “Add_One_Performance_Ranking” sensors can even be added. Syntax is {add/remove}_n, e.g., add_3, remove_4.

NB: When performing performance ranking, remove_* should be used

only together with the Remove_One_Performance_Ranking, and add_* should only be used with Add_One_Performance_Ranking.

(optional, default: remove_1)

Exemplary Call

See the description of SensorSelectionBase for an example usage of this node.

Author:

Mario Krell (mario.krell@dfki.de) & David Feess

Created:

2011/09/23

POSSIBLE NODE NAMES:
 
  • Sensor_Selection_Ranking
  • SensorSelectionRanking
  • Electrode_Selection_Ranking
  • SensorSelectionRankingNode
POSSIBLE INPUT TYPES:
 
  • TimeSeries

Class Components Summary

_stop_training([debug]) Recast sensor set
_train(data, label) Save the data
add_sensors(n) Iteratively add n sensors to the current subset
create_ranker(ranking_name, ranking_spec) A ranking method should return a sorted list of tuples (sensor, score), Where the first element is the worst sensor with the lowest score.
input_types
remove_sensors(n) Iteratively remove n sensors from the current (sub)set
store_state(result_dir[, index]) Store the names of the selected sensors into result_dir
__init__(ranking_spec, ranking, recast_method='remove_1', **kwargs)[source]
create_ranker(ranking_name, ranking_spec)[source]

A ranking method should return a sorted list of tuples (sensor, score), Where the first element is the worst sensor with the lowest score. Thus, in cases where a high score denotes a bad sensor: swap sign!

_train(data, label)[source]

Save the data

The actual training is done after all data has been collected.

_stop_training(debug=False)[source]

Recast sensor set

remove_sensors(n)[source]

Iteratively remove n sensors from the current (sub)set

add_sensors(n)[source]

Iteratively add n sensors to the current subset

store_state(result_dir, index=None)[source]

Store the names of the selected sensors into result_dir

input_types = ['TimeSeries']

SensorSelectionSSNRNode

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.SensorSelectionSSNRNode(num_selected_sensors, erp_class_label='Target', retained_channels=None, search_heuristic='evolutionary_algorithm', objective_function='ssnr_vs', population_size=20, num_survivors=8, mutant_ratio=0.3, crossover_ratio=0.3, iterations=1000, **kwargs)[source]

Bases: pySPACE.missions.nodes.spatial_filtering.sensor_selection.SensorSelectionBase

Select sensors based on maximizing the SSNR

This node searches for an optimal sensor configuration for a given number of sensors. It can use different meta-heuristics (like evolutionary algorithms or recursive backward elimination) for this search. The objective function that shall be maximized can be configured and is based on the signal to signal-plus-noise ratio (SSNR).

Parameters
erp_class_label:
 

Label of the class for which an ERP should be evoked. For instance “Target” for a P300 oddball paradigm.

num_selected_sensors:
 

Determines how many sensors are kept.

retained_channels:
 

The number of pseudo-channels that are kept after xDAWN filtering when using virtual sensor space. Even though this node only selects sensors and does no spatial filtering, this information is relevant since the SSNR after xDAWN spatial filtering is used in objective functions in virtual sensor space and the SSNR depends on the number of pseudo-channels. If one does not use virtual sensor space, this information can be ignored.

(optional, default: num_selected_sensors)

search_heuristic:
 

The search heuristic that is used to search an optimal sensor configuration. Can be either “evolutionary_search” or “recursive_backward_elimination”.

(optional, default: “evolutionary_algorithm”)

objective_function:
 

The objective function that is used to determine which sensor selection are well suited and which less suited. Available objective functions are “ssnr_vs” (the signal to signal-plus-noise ratio in virtual sensor space), “ssnr_as” (the signal to signal-plus-noise ratio in actual sensor space), “ssnr_vs_test” (the minimum signal to signal-plus-noise ratio in virtual sensor space when one of selected sensors wouldn’t be present)

(optional, default: “ssnr_vs”)

population_size:
 

The number of individuals of which one generation of the EA consists of. Each individual corresponds to one sensor configuration.

(optional, default: 20)

num_survivors:

The number of individuals which survive at the end of a generation of the EA. The ratio of num_survivors to population_size determines the selection pressure.

(optional, default: 8)

mutant_ratio:

The ratio of the next generation that consist of survivors that a underwent a mutation.

(optional, default: 0.3)

crossover_ratio:
 

The ratio of the next generation that consist of offspring of two survivors that were crossovered.

(optional, default: 0.3)

iterations:

The number of sensor configurations that are evaluated before the EA terminates. The larger this value, the better performance (higher SSNR) can be expected but the computation time increases, too.

(optional, default: 1000)

Exemplary Call

-
    node : Sensor_Selection_SSNR
    parameters :
         erp_class_label : "Target"
         num_selected_sensors : 8
         retained_channels : 4
         search_heuristic : "evolutionary_algorithm"
         iterations : 1000
         mutant_ratio : 0.3
         crossover_ratio : 0.3
         diversity_support : 0.0
         objective_function : "ssnr_vs"
Author:

Jan Hendrik Metzen (jhm@informatik.uni-bremen.de)

Created:

2011/08/22

POSSIBLE NODE NAMES:
 
  • Electrode_Selection_SSNR
  • SensorSelectionSSNRNode
  • Sensor_Selection_SSNR
  • SensorSelectionSSNR
POSSIBLE INPUT TYPES:
 
  • TimeSeries

Class Components Summary

_stop_training([debug])
_train(data, label) Train node on given example data for class label.
input_types
__init__(num_selected_sensors, erp_class_label='Target', retained_channels=None, search_heuristic='evolutionary_algorithm', objective_function='ssnr_vs', population_size=20, num_survivors=8, mutant_ratio=0.3, crossover_ratio=0.3, iterations=1000, **kwargs)[source]
_train(data, label)[source]

Train node on given example data for class label.

_stop_training(debug=False)[source]
input_types = ['TimeSeries']

PerformanceRanker

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.PerformanceRanker(ranking_spec)[source]

Bases: object

Rank sensors by performance after evaluating classification flows

This class provides the functionality to evaluate different classification flows. Every flow has an sensor_identifier string associated. Afterwards, the classification performances (or a derived value - see std_weight parameter) are sorted and returned together with the associated identifier.

Note

Classification performances are multiplied with (-1). In this way, high performances appear first in the sorted results.

The flows differ in the sensors/channels that are used by using multiple Channel Name Selection (CNS) nodes. The way how these CNS nodes are generated, however, is specific for every particular selection procedure (such as “remove one backwards elimination” vs. “add one forward assembly”). The actual generation of the flows happens in generate_cns_nodes. This template class only has a dummy for that method - overwrite it in your ranker! See RemoveOnePerformanceRanker or AddOnePerformanceRanker for examples.

Parameters
flow:

The processing chain (YAML readable). Usually, the flow will at least consist of a CV-Splitter, a classifier, and a PerformanceSinkNode. See the documentation of SensorSelectionBase for an example.

metric:

The metric for the classification performance used for the calculation of the ranking, if a performance value is used.

(optional, default: Balanced_accuracy)

std_weight:

As a result of cross validation often more than one performance result (p) per sensor set is calculated. The score (s) of one particular constellation is thus computed by calculating

s = mean(p) - \text{std\_weight} \cdot \text{std\_dev}(p)

Hence, for std_weight = 0 the mean is used. With increasing std_weight large spreads get penalized more strongly.

(optional, default: 0)

runs:

May be specified to perform multiple runs (and thus different CV-Splits)

(optional, default: 1)

pool_size:

May be specified to achieve parallelization of the classification subflow as normally only the main flow is parallelled.

Note

Currently a pool size larger than 1 will not work with the MulticoreBackend, because multiprocessing can’t be nested. Use loadl backend instead or no pool size!

(optional, default: 1)

Author:Mario Krell (mario.krell@dfki.de) & David Feess
Created:2011/09/23

Class Components Summary

generate_cns_nodes(selected_channels, ...) This method has to be overwritten by the different sensor selection nodes
get_ranking(selected_channels, training_data) Compute the ranking of the selected channels.
__init__(ranking_spec)[source]
get_ranking(selected_channels, training_data)[source]

Compute the ranking of the selected channels.

generate_cns_nodes(selected_channels, training_data)[source]

This method has to be overwritten by the different sensor selection nodes

__weakref__

list of weak references to the object (if defined)

RemoveOnePerformanceRanker

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.RemoveOnePerformanceRanker(**kwargs)[source]

Bases: pySPACE.missions.nodes.spatial_filtering.sensor_selection.PerformanceRanker

Rank sensors by evaluating if classification performance drops without them

Consider a set of n sensors. This ranker will always remove one sensor creating n-1 sized subsets. Every size n-1 subset is evaluated.

NB: high performance == Unimportant sensor == good sensor to remove

See the description of PerformanceRanker for the required parameters.

Author:Mario Krell (mario.krell@dfki.de) & David Feess
Created:2011/09/23

Class Components Summary

generate_cns_nodes(selected_channels, ...) Generate Channel Name Selection Nodes that use the current channels minus 1 ..
__init__(**kwargs)[source]
generate_cns_nodes(selected_channels, training_data)[source]

Generate Channel Name Selection Nodes that use the current channels minus 1 .. todo:: training_data parameter is not necessary!

AddOnePerformanceRanker

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.AddOnePerformanceRanker(**kwargs)[source]

Bases: pySPACE.missions.nodes.spatial_filtering.sensor_selection.PerformanceRanker

Rank sensors by evaluating performance increase on usage

Consider a set N of sensors and a fixed subset K of the sensors in N. This ranker will always add one sensor of NK to K creating k+1 sized subsets. Every subset is than evaluated. The score of the added sensors is determined by the classification performance, s.t. high performance == good sensor to add

See the description of PerformanceRanker for the required parameters.

Author:Mario Krell (mario.krell@dfki.de) & David Feess
Created:2011/09/23

Class Components Summary

generate_cns_nodes(selected_channels, ...) Generate Channel Name Selection Nodes that use the current channels plus 1
__init__(**kwargs)[source]
generate_cns_nodes(selected_channels, training_data)[source]

Generate Channel Name Selection Nodes that use the current channels plus 1

CoefficientRanker

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.CoefficientRanker(ranking_spec, run_number)[source]

Bases: object

Get a ranking from the second last processing node

This ranking is given by this node, by adding up channel weights of linear classifiers or spatial filters. The details remain to the used node (last one in the node chain before sink node) and its method get_sensor_ranking.

Parameters

flow:

The classification flow (YAML readable). Usually, the flow will at least consist of a CV-Splitter, a classifier , and a Classification_Performance_Sink. See the documentation of SensorSelectionBase for an example.

(optional, default: 1)

Class Components Summary

get_ranking(selected_channels, training_data)
__init__(ranking_spec, run_number)[source]
get_ranking(selected_channels, training_data)[source]
__weakref__

list of weak references to the object (if defined)

EvolutionaryAlgorithm

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.EvolutionaryAlgorithm(total_elements, num_selected_elements, population_size, num_survivors, mutant_ratio, crossover_ratio)[source]

Bases: object

Black-box optimization using an evolutionary algorithm

This implementation is tailored for the specific case that one wants to select M out of N elements and is looking for the M elements that maximize an objective function. For simplicity, it is assumed, the one works on the indices, i.e. the N-elementary set is {0,1,...,N-1}.

One may either provide the objective function to the object and let it autonomously optimize this function or use its “ask and tell” interface and keep control over the optimization procedure.

Parameters
total_elements:The number of total elements (i.e. N)
num_selected_elements:
 The number of elements to be selected (i.e. M)
population_size:
 The number of individuals of which one generation of the EA consists of.
num_survivors:The number of individuals which survive at the end of a generation. The ratio of num_survivors to population_size determines the selection pressure.
mutant_ratio:The ratio of the next generation that consist of survivors that a underwent a mutation.
crossover_ratio:
 The ratio of the next generation that consist of offspring of two survivors that were crossovered.

Class Components Summary

_crossover(parent1, parent2) Create offspring by crossover of two parent individuals.
_mutate(individual) Mutate the given individual with the given probability.
get_best_elements() Return the individual with the maximal fitness.
get_current_elements() Return the currently active individual.
optimize(objective_function, evaluations) Search for maximum of objective_function
tell_fitness(fitness) Add a fitness sample for the current individual.
__init__(total_elements, num_selected_elements, population_size, num_survivors, mutant_ratio, crossover_ratio)[source]
optimize(objective_function, evaluations)[source]

Search for maximum of objective_function

Search for maximum of the given objective_function. Restrict number of evaluations of objective function to evaluations.

get_best_elements()[source]

Return the individual with the maximal fitness.

get_current_elements()[source]

Return the currently active individual.

tell_fitness(fitness)[source]

Add a fitness sample for the current individual.

_mutate(individual)[source]

Mutate the given individual with the given probability.

_crossover(parent1, parent2)[source]

Create offspring by crossover of two parent individuals.

__weakref__

list of weak references to the object (if defined)

RecursiveBackwardElimination

class pySPACE.missions.nodes.spatial_filtering.sensor_selection.RecursiveBackwardElimination(total_elements, num_selected_elements=None)[source]

Bases: object

Black-box optimization using recursive backward elimination

This implementation is tailored for the specific case that one wants to select M out of N elements and is looking for the M elements that maximize an objective function. For simplicity, it is assumed, the one works on the indices, i.e. the N-elementary set is {0,1,...,N-1}.

One may either call optimize which returns a set of M sensors that are selected using recursive backward elimination or call rank which returns a ranking of all sensors. For rank the specific value of M is not relevant and may be omitted.

Parameters
total_elements:The number of total elements (i.e. N)
num_selected_elements:
 The number of elements to be selected (i.e. M)

Class Components Summary

optimize(objective_function, \*args, \*\*kwargs) Search for an optimal configuration consisting of M elements
rank(objective_function, \*args, \*\*kwargs) Rank the elements.
__init__(total_elements, num_selected_elements=None)[source]
optimize(objective_function, *args, **kwargs)[source]

Search for an optimal configuration consisting of M elements

rank(objective_function, *args, **kwargs)[source]

Rank the elements.

__weakref__

list of weak references to the object (if defined)

Function

evaluate_sensor_selection()

pySPACE.missions.nodes.spatial_filtering.sensor_selection.evaluate_sensor_selection(cns, flow, metric, w, sensor_identifier, training_data, runs=1)[source]

Execute the evaluation flow