Wir haben ein praktisches Tool colt
zum Schreiben von Anwendungseinstellungen wie maschinellem Lernen erstellt.
Kurz gesagt, colt
ist ein Tool zum Schreiben von Einstellungen wie AllenNLP
.
Ich habe im Titel "Maschinelles Lernen" geschrieben, aber ich denke, es kann zum Einstellen vieler Anwendungen verwendet werden, nicht nur für maschinelles Lernen.
Beim Experimentieren mit Modellen für maschinelles Lernen stellen wir häufig fest, dass argparse
und Hydra
zum Verwalten von Hyperparametern verwendet werden.
Ich denke, das Problem bei vielen dieser vorhandenen Parameterverwaltungswerkzeuge besteht darin, dass sich auch der Parameterladeprozess ändern muss, wenn sich das Modell erheblich ändert.
Zum Beispiel (ein sehr aggressives Beispiel), SVC
von scikit-learn
Ich wollte generierte / sklearn.svm.SVC.html (Highlight = svc # sklearn-svm-svc) verwenden und schrieb eine Einstellung zum Lesen von Parametern wie "C", "Kernel", "class_weight" in "argparse". , RandomForestClassifier
zum Laden der Einstellungen Ist es notwendig, auch das Teil neu zu schreiben?
Wenn Sie ein Ensemble-Modell wie [StackingClassifier
] festlegen möchten (https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.StackingClassifier.html?highlight=stacking#sklearn-ensemble-stackingclassifier) , Wenn Sie den Basisklassifikator und den Meta-Klassifikator festlegen möchten, fragen Sie sich, wie Sie die Einstellungen schreiben sollen.
AllenNLP
Eines der Mittel zur Lösung dieser Probleme ist die von AllenNLP
übernommene ** Registerfunktion **, die ein Deep-Learning-Framework für die Verarbeitung natürlicher Sprache darstellt. Es gibt.
Hier werde ich diese ** Registerfunktion ** ein wenig erklären. Wenn Sie es wissen, überspringen Sie es bitte.
AllenNLP beschreibt die Einstellungen im JSON-Format. Im Folgenden sind einige Einstellungen für das Satzklassifizierungsmodell aufgeführt:
"model": {
"type": "basic_classifier",
"text_field_embedder": {
"token_embedders": {
"tokens": {
"type": "embedding",
"embedding_dim": 10,
"trainable": true
}
}
},
"seq2vec_encoder": {
"type": "cnn",
"num_filters": 8,
"embedding_dim": 10,
"output_dim": 16
}
},
Geben Sie die Klasse an, die Sie mit type
verwenden möchten, und legen Sie die Parameter im Feld derselben Ebene fest.
Schauen wir uns auch den Code für basic_classifier
und cnn
an. Die Einstellungselemente entsprechen den Argumenten der Methode __init__
:
@Model.register("basic_classifier")
class BasicClassifier(Model):
def __init__(
self,
...,
text_field_embedder: TextFieldEmbedder,
seq2vec_encoder: Seq2VecEncoder,
...,
) -> None:
...
@Seq2VecEncoder.register("cnn")
class CnnEncoder(Seq2VecEncoder):
def __init__(self,
embedding_dim: int,
num_filters: int,
ngram_filter_sizes: Tuple[int, ...] = (2, 3, 4, 5),
conv_layer_activation: Activation = None,
output_dim: Optional[int] = None) -> None:
Wenn Sie Klassen beim Dekorator register
registrieren, können Sie diese Klassen in den Einstellungen angeben.
Mit AllenNLP
können Sie die Einstellungen einer Klasse schreiben, indem Sie einfach eine Klasse erstellen und registrieren
.
Hier heißt diese Funktion ** Registerfunktion **.
Da die Registerfunktion eine Klasse mit ihren Einstellungen verknüpft, ist es nicht erforderlich, den Einstellungslesevorgang entsprechend der Modelländerung zu ändern.
Sie können verschiedene Komponenten des Modells einfach über die Einstellungen ersetzen. Um den "Typ" von "seq2vec_encoder" von "cnn" in "lstm" zu ändern, schreiben Sie einfach die Einstellungen wie folgt um ("lstm" ist bereits in "AllenNLP" enthalten):
"seq2vec_encoder": {
"type": "lstm",
"num_layers": 1,
"input_size": 10,
"hidden_size": 16
}
colt
colt
ist ein Tool, um dieselbe Funktion wie die ** Registerfunktion ** von AllenNLP
zu realisieren.
Mit "colt" können Sie ganz einfach Einstellungen vornehmen, die flexibel und resistent gegen Codeänderungen wie "AllenNLP" sind.
Es werden auch einige Funktionen implementiert, die in "AllenNLP" nicht enthalten sind, um die Verwendung in mehreren Fällen zu vereinfachen.
Hier ist ein Beispiel für die Verwendung von colt
:
import typing as tp
import colt
@colt.register("foo")
class Foo:
def __init__(self, message: str) -> None:
self.message = message
@colt.register("bar")
class Bar:
def __init__(self, foos: tp.List[Foo]) -> None: # ---- (*)
self.foos = foos
config = {
"@type": "bar", # `@type`Geben Sie die Klasse mit an
"foos": [
{"message": "hello"}, #Der Typ hier ist(*)Abgeleitet aus dem Typ Hinweis von
{"message": "world"},
]
}
bar = colt.build(config) #Erstellen Sie Objekte aus config
assert isinstance(bar, Bar)
print(" ".join(foo.message for foo in bar.foos)) # => "hello world"
Registrieren Sie die Klasse mit colt.register (" <Klassenkennung> ")
.
Beschreiben Sie auf der Einstellungsseite im Format "{" @type ":"
Wenn Sie ein Objekt aus einer Einstellung erstellen, rufen Sie "colt.build (
Wenn die Einstellung kein Feld "@ type" enthält und der Typhinweis in das entsprechende Argument geschrieben ist, wird das Objekt basierend auf dem Typhinweis erstellt. Im obigen Beispiel wird der Typhinweis "List [Foo]" dem Argument "foos" von "Bar" gegeben, sodass der Inhalt von "foos" in "config" in Objekte der Klasse "Foo" konvertiert wird.
Typhinweise sind für colt
nicht immer erforderlich.
Wenn Sie keine Typhinweise verwenden, schreiben Sie "@ type", ohne es wegzulassen.
config = {
"@type": "bar",
"foos": [
{"@type": "bar", "message": "hello"},
{"@type": "bar", "message": "world"},
]
}
Wenn es keinen "@ type" oder Typhinweis gibt, wird er einfach als "dict" behandelt.
Sie können colt
auch für vorhandene Modelle verwenden, die in scikit-learn
usw. enthalten sind.
Wenn der durch "@ type" angegebene Name nicht "registriert" ist, wird er automatisch importiert.
Das Folgende ist ein Beispiel für die Verwendung von "StackingClassifier" von "scikit-learn":
import colt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
config = {
"@type": "sklearn.ensemble.StackingClassifier",
"estimators": [
("rfc", { "@type": "sklearn.ensemble.RandomForestClassifier",
"n_estimators": 10 }),
("svc", { "@type": "sklearn.svm.SVC",
"gamma": "scale" }),
],
"final_estimator": {
"@type": "sklearn.linear_model.LogisticRegression",
"C": 5.0,
},
"cv": 5,
}
X, y = load_iris(return_X_y=True)
X_train, X_valid, y_train, y_valid = train_test_split(X, y)
model = colt.build(config)
model.fit(X_train, y_train)
valid_accuracy = model.score(X_valid, y_valid)
print(f"valid_accuracy: {valid_accuracy}")
Im obigen Beispiel kann das in "config" beschriebene Modell ersetzt werden, wenn es die API "scikit-learn" hat. Zum Beispiel zur Rastersuche "LGBMClassifier" mit "GridSearchCV":
config = {
"@type": "sklearn.model_selection.GridSearchCV",
"estimator": {
"@type": "lightgbm.LGBMClassifier",
"boosting_type": "gbdt",
"objective": "multiclass",
},
"param_grid": {
"n_estimators": [10, 50, 100],
"num_leaves": [16, 32, 64],
"max_depth": [-1, 4, 16],
}
}
colt
bietet keine Funktion zum Lesen von Einstellungen aus einer Datei.
Wenn Sie die Einstellungen aus einer Datei lesen möchten, konvertieren Sie Ihr Lieblingsformat wie JSON / Jsonnet oder YAML in "diktieren" und übergeben Sie es an "colt".
Wenn Sie sich in mehreren verschiedenen Dateien registrieren, müssen alle Klassen importiert werden, die zum Zeitpunkt von colt.build verwendet werden sollen.
colt
kann colt.import_modules
verwenden, um rekursiv mehrere Module zu importieren.
Betrachten Sie beispielsweise die folgende Dateistruktur:
.
|-- main.py
`- models
|-- __init__.py
|-- foo.py
`- bar.py
Nehmen wir an, dass "models / foo.py" und "models / bar.py" die "Foo" -Klasse und die "Bar" -Klasse "register" haben und "main.py" "colt.build". ..
Verwenden Sie colt.import_modules ([" <Modulname> ", ...])
in main.py
wie folgt.
main.py
colt.import_modules(["models"])
colt.build(config)
Wenn Sie eine Liste von Modulnamen an colt.import_modules
übergeben, wird jedes Modul und darunter rekursiv importiert.
Im obigen Beispiel haben wir "[" models "]" als Argument übergeben, sodass alle Module unter dem Modul "models" importiert werden und "Foo", "Bar" verfügbar sind.
Wenn Sie Positionsargumente in den Einstellungen beschreiben, geben Sie "*" als Schlüssel an und übergeben Sie eine Liste (oder ein Taple) von Positionsargumenten als Wert.
@colt.register("foo")
class Foo:
def __init__(self, x, y):
...
config = {"@type": "foo", "*": ["x", "y"]}
Standardmäßig erstellt colt
ein Objekt, indem das Klassenargument an __init__
übergeben wird.
Wenn Sie ein Objekt mit einer anderen Methode als "init" erstellen möchten, können Sie Folgendes angeben:
@colt.register("foo", constructor="build")
class FooWrapper:
@classmethod
def build(cls, *args, **kwargs) -> Foo:
...
Dies ist praktisch, wenn Sie es als Wrapper für eine andere Klasse verwenden möchten.
Sondertasten wie "@ type" und "", die von "colt" verwendet werden, können geändert werden. Wenn Sie beispielsweise "@ type" in "@" und "" in "+" ändern möchten, geben Sie dies in "colt.build" als Argument an:
colt.build(config, typekey="@", argskey="+")
Wenn Sie die allgemeinen Einstellungen beibehalten möchten, verwenden Sie "ColtBuilder".
builder = colt.ColtBuilder(typekey="@", argskey="+")
builder(config_one)
builder(config_two)
Ich habe kaggles Titanic-Wettbewerb mit colt
ausprobiert.
https://github.com/altescy/colt/tree/master/examples/titanic
Verwenden von pdpipe
und scikit-learn
zum Erstellen von Features und Modellen Der größte Teil der Verarbeitung vom Lernen bis zur Bewertung kann eingestellt werden.
Alle Einstellungen werden unter configs
als Jsonnet beschrieben. Ich hoffe, es wird hilfreich sein, wenn Sie colt
verwenden.
Wir haben die Funktionen und Verwendungsbeispiele von colt
vorgestellt.
Ich hoffe es hilft dir beim Schreiben der Einstellungen.
Außerdem basiert die Funktionalität von colt
auf einem großartigen Framework namens AllenNLP
.
AllenNLP
enthält viele nützliche Ideen für viele maschinelle Lernaufgaben sowie für die Verarbeitung natürlicher Sprachen. Wenn Sie also interessiert sind, verwenden Sie diese bitte.
Recommended Posts