great-ai-interview-task/deploy_done.ipynb

230 lines
40 KiB
Text

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# todo: export the model from train.ipynb\n",
"\n",
"# todo: copy import from train.ipynb\n",
"# todo: copy normalize() from train.ipynb\n",
"# todo: copy predict() from train.ipynb\n",
"\n",
"# todo: inject saved model into predict()\n",
"# todo: turn predict() into a GreatAI service\n",
"\n",
"# todo: log prediction into output trace"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[38;5;226mEnvironment variable ENVIRONMENT is not set, defaulting to development mode ‼️\u001b[0m\n",
"\u001b[38;5;226mCannot find credentials files, defaulting to using ParallelTinyDbDriver\u001b[0m\n",
"\u001b[38;5;226mThe selected tracing database (ParallelTinyDbDriver) is not recommended for production\u001b[0m\n",
"\u001b[38;5;226mCannot find credentials files, defaulting to using LargeFileLocal\u001b[0m\n",
"\u001b[38;5;39mGreatAI (v0.1.10): configured ✅\u001b[0m\n",
"\u001b[38;5;39m 🔩 tracing_database: ParallelTinyDbDriver\u001b[0m\n",
"\u001b[38;5;39m 🔩 large_file_implementation: LargeFileLocal\u001b[0m\n",
"\u001b[38;5;39m 🔩 is_production: False\u001b[0m\n",
"\u001b[38;5;39m 🔩 should_log_exception_stack: True\u001b[0m\n",
"\u001b[38;5;39m 🔩 prediction_cache_size: 512\u001b[0m\n",
"\u001b[38;5;39m 🔩 dashboard_table_size: 50\u001b[0m\n",
"\u001b[38;5;226mYou still need to check whether you follow all best practices before trusting your deployment.\u001b[0m\n",
"\u001b[38;5;226m> Find out more at https://se-ml.github.io/practices\u001b[0m\n",
"\u001b[38;5;39mFetching cached versions of financial-sentiment\u001b[0m\n",
"\u001b[38;5;39mLatest version of financial-sentiment is 1 (from versions: 0, 1)\u001b[0m\n",
"\u001b[38;5;39mFile financial-sentiment-1 found in cache\u001b[0m\n"
]
}
],
"source": [
"from great_ai.utilities import clean\n",
"from great_ai import use_model, GreatAI, log_metric, ClassificationOutput\n",
"import re\n",
"\n",
"def normalize(text: str) -> str:\n",
" cleaned = clean(text, convert_to_ascii=True).lower()\n",
" return re.sub(r\"[^a-z]+\", \" \", cleaned)\n",
"\n",
"@GreatAI.create\n",
"@use_model('financial-sentiment')\n",
"def predict_financial_sentiment(text: str, model) -> ClassificationOutput:\n",
" \"\"\"Classify news articles into Negative, Neutral, or Positive classes using a linear SVM.\"\"\"\n",
" text = normalize(text)\n",
" features = model.named_steps[\"tfidfvectorizer\"].transform([text])\n",
" prediction = model.named_steps[\"sgdclassifier\"].predict(features)[0]\n",
"\n",
" explanation = [\n",
" (feature_name, weight)\n",
" for weight, feature_name in sorted(\n",
" (\n",
" (feature_weight * feature, feature_name)\n",
" for feature_name, feature_weight, feature in zip(\n",
" model.named_steps[\"tfidfvectorizer\"].get_feature_names_out(),\n",
" model.named_steps[\"sgdclassifier\"].coef_[list(model.named_steps[\"sgdclassifier\"].classes_).index(prediction)],\n",
" features.toarray()[0],\n",
" )\n",
" if feature * feature_weight != 0\n",
" ),\n",
" reverse=True,\n",
" )\n",
" ][:10]\n",
"\n",
" log_metric('prediction', prediction, disable_logging=True)\n",
"\n",
" return prediction, explanation"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 200/200 [00:24<00:00, 8.03it/s]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" precision recall f1-score support\n",
"\n",
" negative 0.45 0.17 0.25 29\n",
" neutral 0.70 0.85 0.77 102\n",
" positive 0.77 0.72 0.75 69\n",
"\n",
" accuracy 0.71 200\n",
" macro avg 0.64 0.58 0.59 200\n",
"weighted avg 0.69 0.71 0.69 200\n",
"\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 720x720 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# todo: add integration test (copy metric derivation from train.ipynb)\n",
"\n",
"if __name__ == '__main__':\n",
" from great_ai import query_ground_truth\n",
" import matplotlib.pyplot as plt\n",
" from sklearn import metrics\n",
"\n",
" test_split = query_ground_truth('test', return_max_count=200)\n",
"\n",
" traces = predict_financial_sentiment.process_batch([t.input for t in test_split])\n",
" y_predicted = [t.output[0] for t in traces]\n",
" y_test = [t.output for t in test_split]\n",
"\n",
" %matplotlib inline\n",
" plt.rcParams[\"figure.figsize\"] = (10, 10)\n",
" plt.rcParams[\"font.size\"] = 16\n",
"\n",
" print(metrics.classification_report(y_test, y_predicted))\n",
" metrics.ConfusionMatrixDisplay.from_predictions(\n",
" y_true=y_test,\n",
" y_pred=y_predicted,\n",
" xticks_rotation=\"vertical\",\n",
" normalize=\"pred\",\n",
" values_format=\".2f\",\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[38;5;39m2022-08-11 11:14:04 | INFO | Converting notebook to Python script\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:04 | INFO | Found `predict_financial_sentiment` to be the GreatAI app \u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:04 | INFO | Uvicorn running on http://0.0.0.0:6060 (Press CTRL+C to quit)\u001b[0m\n",
"\u001b[38;5;226m2022-08-11 11:14:06 | WARNING | Environment variable ENVIRONMENT is not set, defaulting to development mode ‼️\u001b[0m\n",
"\u001b[38;5;226m2022-08-11 11:14:06 | WARNING | Cannot find credentials files, defaulting to using ParallelTinyDbDriver\u001b[0m\n",
"\u001b[38;5;226m2022-08-11 11:14:06 | WARNING | The selected tracing database (ParallelTinyDbDriver) is not recommended for production\u001b[0m\n",
"\u001b[38;5;226m2022-08-11 11:14:06 | WARNING | Cannot find credentials files, defaulting to using LargeFileLocal\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | GreatAI (v0.1.10): configured ✅\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | 🔩 tracing_database: ParallelTinyDbDriver\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | 🔩 large_file_implementation: LargeFileLocal\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | 🔩 is_production: False\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | 🔩 should_log_exception_stack: True\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | 🔩 prediction_cache_size: 512\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | 🔩 dashboard_table_size: 50\u001b[0m\n",
"\u001b[38;5;226m2022-08-11 11:14:06 | WARNING | You still need to check whether you follow all best practices before trusting your deployment.\u001b[0m\n",
"\u001b[38;5;226m2022-08-11 11:14:06 | WARNING | > Find out more at https://se-ml.github.io/practices\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | Fetching cached versions of financial-sentiment\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | Latest version of financial-sentiment is 1 (from versions: 0, 1)\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | File financial-sentiment-1 found in cache\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | Started server process [7439]\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | Waiting for application startup.\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:06 | INFO | Application startup complete.\u001b[0m\n",
"^C\n",
"\u001b[38;5;39m2022-08-11 11:14:09 | INFO | Shutting down\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:09 | INFO | Waiting for application shutdown.\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:09 | INFO | Application shutdown complete.\u001b[0m\n",
"\u001b[38;5;39m2022-08-11 11:14:09 | INFO | Finished server process [7439]\u001b[0m\n"
]
}
],
"source": [
"# todo: serve prediction model\n",
"# todo: open dashboard\n",
"\n",
"!great-ai deploy_done.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.5 ('.env': venv)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "2d14168167fa54a6b45c0bc59cb2c3f9a595bd48203d3180b96450e9d825e160"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}