Come accoppiare gli algoritmi concatenati

1

Ho un algoritmo di ricerca che viene utilizzato in combinazione con un algoritmo di apprendimento automatico. Ho separato i due perché volevo essere in grado di scambiare al volo algoritmi di ricerca. Tuttavia, l'accoppiamento è attualmente troppo stretto. Assomiglia a qualcosa:

class ML_Algorithm:

    def __init__(self,observers):
        import someMlLibrary
        self.observers = observers 
        self.classifier = someMlLibrary.model()
        self.searchWindow = SearchingWindow(self.__Classify)


    def Train(self, trainingData):
        preprocessedOutput = self.__Preprocess(trainingData)
        transformedOutput = self.__Transform(preprocessedOutput)
        self.classifier.fit(transformedOutput)


    def __call__(self, data):
        # The main entry point for all the processing
        self.searchWindow.AddData(data)
        for output in searchWindow:
           self.UpdateObservers(output)

    def __Classify(self, dataSubset):
        preprocessedOutput = self.__Preprocess(dataSubset)
        transformedOutput = self.__Transform(preprocessedOutput)
        return self.classifier.predict(transformedOutput)

    def __Prepocess(self,data):
        import someLibrary
        return someLibrary.doSomething(data)

    def __Transform(self,data):
        import someOtherLibrary
        return someOtherLibrary.doSomething(data)


    def UpdateObservers(self, output):
        for observer in self.observers:
            observer.OnOutput(output)

class Observer:

    def OnOutput(self, output):
        pass

class SearchingWindow:
    def __init__(self, fn, negativeResult=0):
        from collections import deque 
        self.fn = fn
        self.buffer = deque(maxlen=1000)
        self.negativeResult = negativeResult

    def AddData(self, data):
        self.buffer.extend(data)

    def __iter__(self):
         start = 0
         step = 1
         stop = 3*step
         while notDone:
            start, stop, step = self.GetNextStartStopStep(start, stop, step)
            for i in range(start,stop,step):
                dataSubset = self.buffer[start:stop]
                result1, result2, ..., resultN = self.fn(dataSubset)
                if result1 != self.negativeResult:
                    yield dataSubset

Ho realizzato l'accoppiamento stretto quando volevo accedere a result1, ..., resultN per fare alcuni test diagnostici attraverso l'oggetto ML_Algorithm ma non potevo.

Qualsiasi aiuto è molto apprezzato.

    
posta electron_avalanche 03.12.2017 - 01:57
fonte

2 risposte

4

Quello che vuoi è spesso definito come il modello di strategia. Vuoi avere una strategia per la ricerca, che è facile da scambiare. Il modo più semplice per implementare questo è accettare la strategia di ricerca nel costruttore della tua classe principale.

class MyFavoriteAlgorithm:
    def __init__(self, observers, search_algorithm):
        .
        .
        self.search_algorithm = search_algorithm

Se tutte le strategie di ricerca si interfacciano allo stesso modo con il tuo codice, questo ti permetterà di scambiare diversi algoritmi di ricerca ogni volta che vuoi. Puoi anche lasciare un algoritmo di ricerca predefinito se ce n'è uno che vuoi usare più spesso.

    
risposta data 05.12.2017 - 03:12
fonte
0

Vorrei cambiare l'approccio utilizzato, effettuando le seguenti operazioni:

  • Rendi più semplice la classe dell'algoritmo ML: metti solo i metodi train, classify, preprocess e transform (rimuovi gli osservatori e il riferimento concreto alla finestra di ricerca);
  • Metti le cose degli osservatori in SearchingWindow;
  • Iniettare un classificatore ML nella finestra di ricerca, è necessario implementare la stessa interfaccia (metodi Train / Classify)
  • Posiziona il punto di ingresso per l'elaborazione in SearchingWindow (o da qualche altra parte, per favore rimuovilo da ML_Algorithm!)

Ecco un codice per illustrare il mio suggerimento:

#Represents a classification method, therefore it only
#contains methods for training, preprocessing, feature transformation
#and classification
class ML_Algorithm:
    def __init__(self,observers):
        import someMlLibrary
        self.classifier = someMlLibrary.model()

    def Train(self, trainingData):
        preprocessedOutput = self.__Preprocess(trainingData)
        transformedOutput = self.__Transform(preprocessedOutput)
        self.classifier.fit(transformedOutput)

    def Classify(self, dataSubset): #public
        preprocessedOutput = self.__Preprocess(dataSubset)
        transformedOutput = self.__Transform(preprocessedOutput)
        return self.classifier.predict(transformedOutput)

    def __Prepocess(self,data):
        import someLibrary
        return someLibrary.doSomething(data)

    def __Transform(self,data):
        import someOtherLibrary
        return someOtherLibrary.doSomething(data)

#Application observers
class Observer:
    def OnOutput(self, output):
        pass

#Search window, which uses some classifier during the operation
class SearchingWindow:
    def __init__(self, clf, negativeResult=0):
        from collections import deque 
        self.observers = observers 
        self.classifier = clf  #now, the classifier is injected
        self.buffer = deque(maxlen=1000)
        self.negativeResult = negativeResult

    def AddData(self, data):
        self.buffer.extend(data)

    def UpdateObservers(self, output):
        for observer in self.observers:
            observer.OnOutput(output)


    def __call__(self, data):
        # The main entry point for all the processing
        self.searchWindow.AddData(data)
        self.classifier.Train(data)  #The main processing requires training
        for output in self:
           self.UpdateObservers(output) 

    def __iter__(self):
         start = 0
         step = 1
         stop = 3*step
         while notDone:
            start, stop, step = self.GetNextStartStopStep(start, stop, step)
            for i in range(start,stop,step):
                dataSubset = self.buffer[start:stop]
                result1, result2, ..., resultN = self.classifier.Classify(dataSubset)
                if result1 != self.negativeResult:
                    yield dataSubset
    
risposta data 05.12.2017 - 10:33
fonte

Leggi altre domande sui tag