Skip to content

Commit

Permalink
Add RNN Incremental Classes
Browse files Browse the repository at this point in the history
  • Loading branch information
kulbachcedric committed Nov 3, 2022
1 parent 323f32c commit 2bb2bad
Showing 1 changed file with 272 additions and 14 deletions.
286 changes: 272 additions & 14 deletions docs/examples/classification/example_rnn_classification.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -25,19 +25,213 @@
{
"cell_type": "markdown",
"source": [
"## LSTM Model Creation"
"## RNN Model"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"outputs": [],
"source": [
"class RnnModule(torch.nn.Module):\n",
"\n",
" def __init__(self, n_features, hidden_size=1):\n",
" super().__init__()\n",
" self.n_features=n_features\n",
" #self.lstm = torch.nn.LSTM(input_size=n_features, hidden_size=hidden_size, num_layers=1)\n",
" self.rnn = torch.nn.RNN(input_size=n_features, hidden_size=hidden_size, num_layers=1)\n",
" self.softmax = torch.nn.Softmax(dim=-1)\n",
"\n",
" def forward(self, X, **kwargs):\n",
" out, hn = self.rnn(X) # lstm with input, hidden, and internal state\n",
" hn = hn.view(-1, self.rnn.hidden_size)\n",
" return self.softmax(hn)"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "markdown",
"source": [
"### Classification without incremental class adapation strategy"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 3,
"outputs": [
{
"data": {
"text/plain": "Pipeline (\n StandardScaler (\n with_std=True\n ),\n RollingClassifier (\n module=<class '__main__.RnnModule'>\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=<class 'torch.optim.sgd.SGD'>\n lr=0.01\n output_is_logit=True\n is_class_incremental=False\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n )\n)",
"text/html": "<div><div class=\"river-component river-pipeline\"><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">StandardScaler</pre></summary><code class=\"river-estimator-params\">(\n with_std=True\n)\n\n</code></details><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">RollingClassifier</pre></summary><code class=\"river-estimator-params\">(\n module=&lt;class '__main__.RnnModule'&gt;\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=&lt;class 'torch.optim.sgd.SGD'&gt;\n lr=0.01\n output_is_logit=True\n is_class_incremental=False\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n)\n\n</code></details></div><style scoped>\n.river-estimator {\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-pipeline {\n display: flex;\n flex-direction: column;\n align-items: center;\n background: linear-gradient(#000, #000) no-repeat center / 3px 100%;\n}\n\n.river-union {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper > .river-estimator {\n margin-top: 1em;\n}\n\n/* Vertical spacing between steps */\n\n.river-component + .river-component {\n margin-top: 2em;\n}\n\n.river-union > .river-estimator {\n margin-top: 0;\n}\n\n.river-union > .pipeline {\n margin-top: 0;\n}\n\n/* Spacing within a union of estimators */\n\n.river-union > .river-component + .river-component {\n margin-left: 1em;\n}\n\n/* Typography */\n\n.river-estimator-params {\n display: block;\n white-space: pre-wrap;\n font-size: 120%;\n margin-bottom: -1em;\n}\n\n.river-estimator > .river-estimator-params,\n.river-wrapper > .river-details > river-estimator-params {\n background-color: white !important;\n}\n\n.river-estimator-name {\n display: inline;\n margin: 0;\n font-size: 130%;\n}\n\n/* Toggle */\n\n.river-summary {\n display: flex;\n align-items:center;\n cursor: pointer;\n}\n\n.river-summary > div {\n width: 100%;\n}\n</style></div>"
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset = datasets.Keystroke()\n",
"metric = metrics.Accuracy()\n",
"optimizer_fn = torch.optim.SGD\n",
"\n",
"model_pipeline = preprocessing.StandardScaler()\n",
"model_pipeline |= RollingClassifier(\n",
" module=RnnModule,\n",
" loss_fn=\"binary_cross_entropy\",\n",
" optimizer_fn=torch.optim.SGD,\n",
" window_size=20,\n",
" lr=1e-2,\n",
" append_predict=True,\n",
" is_class_incremental=False,\n",
")\n",
"model_pipeline"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 4,
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"20400it [00:59, 342.83it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.019558823529411764\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"for x,y in tqdm(dataset):\n",
" y_pred = model_pipeline.predict_one(x) # make a prediction\n",
" metric = metric.update(y, y_pred) # update the metric\n",
" model = model_pipeline.learn_one(x, y) # make the model learn\n",
"print(f'Accuracy: {metric.get()}')"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "markdown",
"source": [
"### Classification with incremental class adaption strategy"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 5,
"outputs": [
{
"data": {
"text/plain": "Pipeline (\n StandardScaler (\n with_std=True\n ),\n RollingClassifier (\n module=<class '__main__.RnnModule'>\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=<class 'torch.optim.sgd.SGD'>\n lr=0.01\n output_is_logit=True\n is_class_incremental=True\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n )\n)",
"text/html": "<div><div class=\"river-component river-pipeline\"><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">StandardScaler</pre></summary><code class=\"river-estimator-params\">(\n with_std=True\n)\n\n</code></details><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">RollingClassifier</pre></summary><code class=\"river-estimator-params\">(\n module=&lt;class '__main__.RnnModule'&gt;\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=&lt;class 'torch.optim.sgd.SGD'&gt;\n lr=0.01\n output_is_logit=True\n is_class_incremental=True\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n)\n\n</code></details></div><style scoped>\n.river-estimator {\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-pipeline {\n display: flex;\n flex-direction: column;\n align-items: center;\n background: linear-gradient(#000, #000) no-repeat center / 3px 100%;\n}\n\n.river-union {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper > .river-estimator {\n margin-top: 1em;\n}\n\n/* Vertical spacing between steps */\n\n.river-component + .river-component {\n margin-top: 2em;\n}\n\n.river-union > .river-estimator {\n margin-top: 0;\n}\n\n.river-union > .pipeline {\n margin-top: 0;\n}\n\n/* Spacing within a union of estimators */\n\n.river-union > .river-component + .river-component {\n margin-left: 1em;\n}\n\n/* Typography */\n\n.river-estimator-params {\n display: block;\n white-space: pre-wrap;\n font-size: 120%;\n margin-bottom: -1em;\n}\n\n.river-estimator > .river-estimator-params,\n.river-wrapper > .river-details > river-estimator-params {\n background-color: white !important;\n}\n\n.river-estimator-name {\n display: inline;\n margin: 0;\n font-size: 130%;\n}\n\n/* Toggle */\n\n.river-summary {\n display: flex;\n align-items:center;\n cursor: pointer;\n}\n\n.river-summary > div {\n width: 100%;\n}\n</style></div>"
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset = datasets.Keystroke()\n",
"metric = metrics.Accuracy()\n",
"optimizer_fn = torch.optim.SGD\n",
"\n",
"model_pipeline = preprocessing.StandardScaler()\n",
"model_pipeline |= RollingClassifier(\n",
" module=RnnModule,\n",
" loss_fn=\"binary_cross_entropy\",\n",
" optimizer_fn=torch.optim.SGD,\n",
" window_size=20,\n",
" lr=1e-2,\n",
" append_predict=True,\n",
" is_class_incremental=True,\n",
")\n",
"model_pipeline"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 6,
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"20400it [01:07, 301.15it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.09485294117647058\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"for x,y in tqdm(dataset):\n",
" y_pred = model_pipeline.predict_one(x) # make a prediction\n",
" metric = metric.update(y, y_pred) # update the metric\n",
" model = model_pipeline.learn_one(x, y) # make the model learn\n",
"print(f'Accuracy: {metric.get()}')"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "markdown",
"source": [
"## LSTM Model"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class MyModule(torch.nn.Module):\n",
"class LstmModule(torch.nn.Module):\n",
"\n",
" def __init__(self, n_features, hidden_size=1):\n",
" super().__init__()\n",
Expand All @@ -62,17 +256,27 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": "Pipeline (\n StandardScaler (\n with_std=True\n ),\n RollingClassifier (\n module=<class '__main__.LstmModule'>\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=<class 'torch.optim.sgd.SGD'>\n lr=0.01\n output_is_logit=True\n is_class_incremental=False\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n )\n)",
"text/html": "<div><div class=\"river-component river-pipeline\"><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">StandardScaler</pre></summary><code class=\"river-estimator-params\">(\n with_std=True\n)\n\n</code></details><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">RollingClassifier</pre></summary><code class=\"river-estimator-params\">(\n module=&lt;class '__main__.LstmModule'&gt;\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=&lt;class 'torch.optim.sgd.SGD'&gt;\n lr=0.01\n output_is_logit=True\n is_class_incremental=False\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n)\n\n</code></details></div><style scoped>\n.river-estimator {\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-pipeline {\n display: flex;\n flex-direction: column;\n align-items: center;\n background: linear-gradient(#000, #000) no-repeat center / 3px 100%;\n}\n\n.river-union {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper > .river-estimator {\n margin-top: 1em;\n}\n\n/* Vertical spacing between steps */\n\n.river-component + .river-component {\n margin-top: 2em;\n}\n\n.river-union > .river-estimator {\n margin-top: 0;\n}\n\n.river-union > .pipeline {\n margin-top: 0;\n}\n\n/* Spacing within a union of estimators */\n\n.river-union > .river-component + .river-component {\n margin-left: 1em;\n}\n\n/* Typography */\n\n.river-estimator-params {\n display: block;\n white-space: pre-wrap;\n font-size: 120%;\n margin-bottom: -1em;\n}\n\n.river-estimator > .river-estimator-params,\n.river-wrapper > .river-details > river-estimator-params {\n background-color: white !important;\n}\n\n.river-estimator-name {\n display: inline;\n margin: 0;\n font-size: 130%;\n}\n\n/* Toggle */\n\n.river-summary {\n display: flex;\n align-items:center;\n cursor: pointer;\n}\n\n.river-summary > div {\n width: 100%;\n}\n</style></div>"
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset = datasets.Keystroke()\n",
"metric = metrics.Accuracy()\n",
"optimizer_fn = torch.optim.SGD\n",
"\n",
"model_pipeline = preprocessing.StandardScaler()\n",
"model_pipeline |= RollingClassifier(\n",
" module=MyModule,\n",
" module=LstmModule,\n",
" loss_fn=\"binary_cross_entropy\",\n",
" optimizer_fn=torch.optim.SGD,\n",
" window_size=20,\n",
Expand All @@ -84,9 +288,31 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"20400it [02:10, 156.58it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.019558823529411764\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"for x,y in tqdm(dataset):\n",
" y_pred = model_pipeline.predict_one(x) # make a prediction\n",
Expand All @@ -106,16 +332,26 @@
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"execution_count": 10,
"outputs": [
{
"data": {
"text/plain": "Pipeline (\n StandardScaler (\n with_std=True\n ),\n RollingClassifier (\n module=<class '__main__.LstmModule'>\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=<class 'torch.optim.sgd.SGD'>\n lr=0.01\n output_is_logit=True\n is_class_incremental=True\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n )\n)",
"text/html": "<div><div class=\"river-component river-pipeline\"><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">StandardScaler</pre></summary><code class=\"river-estimator-params\">(\n with_std=True\n)\n\n</code></details><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">RollingClassifier</pre></summary><code class=\"river-estimator-params\">(\n module=&lt;class '__main__.LstmModule'&gt;\n loss_fn=\"binary_cross_entropy\"\n optimizer_fn=&lt;class 'torch.optim.sgd.SGD'&gt;\n lr=0.01\n output_is_logit=True\n is_class_incremental=True\n device=\"cpu\"\n seed=42\n window_size=20\n append_predict=True\n)\n\n</code></details></div><style scoped>\n.river-estimator {\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-pipeline {\n display: flex;\n flex-direction: column;\n align-items: center;\n background: linear-gradient(#000, #000) no-repeat center / 3px 100%;\n}\n\n.river-union {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 1em;\n border-style: solid;\n background: white;\n}\n\n.river-wrapper > .river-estimator {\n margin-top: 1em;\n}\n\n/* Vertical spacing between steps */\n\n.river-component + .river-component {\n margin-top: 2em;\n}\n\n.river-union > .river-estimator {\n margin-top: 0;\n}\n\n.river-union > .pipeline {\n margin-top: 0;\n}\n\n/* Spacing within a union of estimators */\n\n.river-union > .river-component + .river-component {\n margin-left: 1em;\n}\n\n/* Typography */\n\n.river-estimator-params {\n display: block;\n white-space: pre-wrap;\n font-size: 120%;\n margin-bottom: -1em;\n}\n\n.river-estimator > .river-estimator-params,\n.river-wrapper > .river-details > river-estimator-params {\n background-color: white !important;\n}\n\n.river-estimator-name {\n display: inline;\n margin: 0;\n font-size: 130%;\n}\n\n/* Toggle */\n\n.river-summary {\n display: flex;\n align-items:center;\n cursor: pointer;\n}\n\n.river-summary > div {\n width: 100%;\n}\n</style></div>"
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataset = datasets.Keystroke()\n",
"metric = metrics.Accuracy()\n",
"optimizer_fn = torch.optim.SGD\n",
"\n",
"model_pipeline = preprocessing.StandardScaler()\n",
"model_pipeline |= RollingClassifier(\n",
" module=MyModule,\n",
" module=LstmModule,\n",
" loss_fn=\"binary_cross_entropy\",\n",
" optimizer_fn=torch.optim.SGD,\n",
" window_size=20,\n",
Expand All @@ -131,8 +367,30 @@
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"execution_count": 11,
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"20400it [02:57, 115.18it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 0.06946078431372549\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"for x,y in tqdm(dataset):\n",
" y_pred = model_pipeline.predict_one(x) # make a prediction\n",
Expand Down

0 comments on commit 2bb2bad

Please sign in to comment.