\n",
"\n",
"## Anomaly Exploration (understanding 'Odd')\n",
"In this notebook we're going to be using the zat Python module for processing, transformation and anomaly detection on Zeek network data. We're going to look at 'normal' http traffic and demonstrate the use of Isolation Forests for anomaly detection. We'll then explore those anomalies with clustering and PCA.\n",
"\n",
"**Software**\n",
"- zat: https://github.com/SuperCowPowers/zat\n",
"- Pandas: https://github.com/pandas-dev/pandas\n",
"- Scikit-Learn: http://scikit-learn.org/stable/index.html\n",
"\n",
"**Techniques**\n",
"- One Hot Encoding: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.get_dummies.html\n",
"- Isolation Forest: http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html\n",
"- PCA: http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html\n",
"\n",
"**Related Notebooks**\n",
"- Zeek to Scikit-Learn: https://nbviewer.jupyter.org/github/SuperCowPowers/zat/blob/main/notebooks/Zeek_to_Scikit_Learn.ipynb\n",
"\n",
"**Note:** A previous version of this notebook used a large http log (1 million rows) but we wanted people to be able to run the notebook themselves, so we've changed it to run on the local example http.log."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"zat: 0.4.4\n",
"Pandas: 1.3.5\n",
"Numpy: 1.22.1\n",
"Scikit Learn Version: 1.0.2\n"
]
}
],
"source": [
"import zat\n",
"from zat.log_to_dataframe import LogToDataFrame\n",
"from zat.dataframe_to_matrix import DataFrameToMatrix\n",
"print('zat: {:s}'.format(zat.__version__))\n",
"import pandas as pd\n",
"print('Pandas: {:s}'.format(pd.__version__))\n",
"import numpy as np\n",
"print('Numpy: {:s}'.format(np.__version__))\n",
"import sklearn\n",
"from sklearn.ensemble import IsolationForest\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.cluster import KMeans\n",
"print('Scikit Learn Version:', sklearn.__version__)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Read in 150 Rows...\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
uid
\n",
"
id.orig_h
\n",
"
id.orig_p
\n",
"
id.resp_h
\n",
"
id.resp_p
\n",
"
trans_depth
\n",
"
method
\n",
"
host
\n",
"
uri
\n",
"
referrer
\n",
"
...
\n",
"
info_msg
\n",
"
filename
\n",
"
tags
\n",
"
username
\n",
"
password
\n",
"
proxied
\n",
"
orig_fuids
\n",
"
orig_mime_types
\n",
"
resp_fuids
\n",
"
resp_mime_types
\n",
"
\n",
"
\n",
"
ts
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
2013-09-15 23:44:27.668081920
\n",
"
CyIaMO7IheOh38Zsi
\n",
"
192.168.33.10
\n",
"
1031
\n",
"
54.245.228.191
\n",
"
80
\n",
"
1
\n",
"
GET
\n",
"
guyspy.com
\n",
"
/
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
(empty)
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
Fnjq3r4R0VGmHVWiN5
\n",
"
text/html
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:27.731702016
\n",
"
CoyZrY2g74UvMMgp4a
\n",
"
192.168.33.10
\n",
"
1032
\n",
"
54.245.228.191
\n",
"
80
\n",
"
1
\n",
"
GET
\n",
"
www.guyspy.com
\n",
"
/
\n",
"
NaN
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
(empty)
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
FCQ5aX37YzsjAKpcv8
\n",
"
text/html
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:28.092921856
\n",
"
CoyZrY2g74UvMMgp4a
\n",
"
192.168.33.10
\n",
"
1032
\n",
"
54.245.228.191
\n",
"
80
\n",
"
2
\n",
"
GET
\n",
"
www.guyspy.com
\n",
"
/wp-content/plugins/slider-pro/css/advanced-sl...
\n",
"
http://www.guyspy.com/
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
(empty)
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
FD9Xu815Hwui3sniSf
\n",
"
text/html
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:28.150300928
\n",
"
CiCKTz4e0fkYYazBS3
\n",
"
192.168.33.10
\n",
"
1040
\n",
"
54.245.228.191
\n",
"
80
\n",
"
1
\n",
"
GET
\n",
"
www.guyspy.com
\n",
"
/wp-content/plugins/contact-form-7/includes/cs...
\n",
"
http://www.guyspy.com/
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
(empty)
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
FMZXWm1yCdsCAU3K9d
\n",
"
text/plain
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:28.150601984
\n",
"
C1YBkC1uuO9bzndRvh
\n",
"
192.168.33.10
\n",
"
1041
\n",
"
54.245.228.191
\n",
"
80
\n",
"
1
\n",
"
GET
\n",
"
www.guyspy.com
\n",
"
/wp-content/plugins/slider-pro/css/slider/adva...
\n",
"
http://www.guyspy.com/
\n",
"
...
\n",
"
NaN
\n",
"
NaN
\n",
"
(empty)
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
FA4NM039Rf9Y8Sn2Rh
\n",
"
text/plain
\n",
"
\n",
" \n",
"
\n",
"
5 rows × 26 columns
\n",
"
"
],
"text/plain": [
" uid id.orig_h id.orig_p \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 CyIaMO7IheOh38Zsi 192.168.33.10 1031 \n",
"2013-09-15 23:44:27.731702016 CoyZrY2g74UvMMgp4a 192.168.33.10 1032 \n",
"2013-09-15 23:44:28.092921856 CoyZrY2g74UvMMgp4a 192.168.33.10 1032 \n",
"2013-09-15 23:44:28.150300928 CiCKTz4e0fkYYazBS3 192.168.33.10 1040 \n",
"2013-09-15 23:44:28.150601984 C1YBkC1uuO9bzndRvh 192.168.33.10 1041 \n",
"\n",
" id.resp_h id.resp_p trans_depth method \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 54.245.228.191 80 1 GET \n",
"2013-09-15 23:44:27.731702016 54.245.228.191 80 1 GET \n",
"2013-09-15 23:44:28.092921856 54.245.228.191 80 2 GET \n",
"2013-09-15 23:44:28.150300928 54.245.228.191 80 1 GET \n",
"2013-09-15 23:44:28.150601984 54.245.228.191 80 1 GET \n",
"\n",
" host \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 guyspy.com \n",
"2013-09-15 23:44:27.731702016 www.guyspy.com \n",
"2013-09-15 23:44:28.092921856 www.guyspy.com \n",
"2013-09-15 23:44:28.150300928 www.guyspy.com \n",
"2013-09-15 23:44:28.150601984 www.guyspy.com \n",
"\n",
" uri \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 / \n",
"2013-09-15 23:44:27.731702016 / \n",
"2013-09-15 23:44:28.092921856 /wp-content/plugins/slider-pro/css/advanced-sl... \n",
"2013-09-15 23:44:28.150300928 /wp-content/plugins/contact-form-7/includes/cs... \n",
"2013-09-15 23:44:28.150601984 /wp-content/plugins/slider-pro/css/slider/adva... \n",
"\n",
" referrer ... info_msg filename \\\n",
"ts ... \n",
"2013-09-15 23:44:27.668081920 NaN ... NaN NaN \n",
"2013-09-15 23:44:27.731702016 NaN ... NaN NaN \n",
"2013-09-15 23:44:28.092921856 http://www.guyspy.com/ ... NaN NaN \n",
"2013-09-15 23:44:28.150300928 http://www.guyspy.com/ ... NaN NaN \n",
"2013-09-15 23:44:28.150601984 http://www.guyspy.com/ ... NaN NaN \n",
"\n",
" tags username password proxied orig_fuids \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 (empty) NaN NaN NaN NaN \n",
"2013-09-15 23:44:27.731702016 (empty) NaN NaN NaN NaN \n",
"2013-09-15 23:44:28.092921856 (empty) NaN NaN NaN NaN \n",
"2013-09-15 23:44:28.150300928 (empty) NaN NaN NaN NaN \n",
"2013-09-15 23:44:28.150601984 (empty) NaN NaN NaN NaN \n",
"\n",
" orig_mime_types resp_fuids \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 NaN Fnjq3r4R0VGmHVWiN5 \n",
"2013-09-15 23:44:27.731702016 NaN FCQ5aX37YzsjAKpcv8 \n",
"2013-09-15 23:44:28.092921856 NaN FD9Xu815Hwui3sniSf \n",
"2013-09-15 23:44:28.150300928 NaN FMZXWm1yCdsCAU3K9d \n",
"2013-09-15 23:44:28.150601984 NaN FA4NM039Rf9Y8Sn2Rh \n",
"\n",
" resp_mime_types \n",
"ts \n",
"2013-09-15 23:44:27.668081920 text/html \n",
"2013-09-15 23:44:27.731702016 text/html \n",
"2013-09-15 23:44:28.092921856 text/html \n",
"2013-09-15 23:44:28.150300928 text/plain \n",
"2013-09-15 23:44:28.150601984 text/plain \n",
"\n",
"[5 rows x 26 columns]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create a Pandas dataframe from the Zeek HTTP log\n",
"log_to_df = LogToDataFrame()\n",
"zeek_df = log_to_df.create_dataframe('../data/http.log')\n",
"print('Read in {:d} Rows...'.format(len(zeek_df)))\n",
"zeek_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"\n",
"## So... what just happened?\n",
"**Yep it was quick... the two little lines of code above turned a Zeek log (any log) into a Pandas DataFrame. The zat package also supports streaming data from dynamic/active logs, handles log rotations and in general tries to make your life a bit easier when doing data analysis and machine learning on Zeek data.**\n",
"\n",
"**Now that we have the data in a dataframe there are a million wonderful things we could do for data munging, processing and analysis but that will have to wait for another time/notebook.**"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# We're going to pick some features that might be interesting\n",
"# some of the features are numerical and some are categorical\n",
"features = ['id.resp_p', 'method', 'resp_mime_types', 'request_body_len']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Our HTTP features are a mix of numeric and categorical data\n",
"When we look at the http records some of the data is numerical and some of it is categorical so we'll need a way of handling both data types in a generalized way. zat has a DataFrameToMatrix class that handles a lot of the details and mechanics of combining numerical and categorical data, we'll use below."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
id.resp_p
\n",
"
method
\n",
"
resp_mime_types
\n",
"
request_body_len
\n",
"
\n",
"
\n",
"
ts
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
2013-09-15 23:44:27.668081920
\n",
"
80
\n",
"
GET
\n",
"
text/html
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:27.731702016
\n",
"
80
\n",
"
GET
\n",
"
text/html
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:28.092921856
\n",
"
80
\n",
"
GET
\n",
"
text/html
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:28.150300928
\n",
"
80
\n",
"
GET
\n",
"
text/plain
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:28.150601984
\n",
"
80
\n",
"
GET
\n",
"
text/plain
\n",
"
0
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id.resp_p method resp_mime_types \\\n",
"ts \n",
"2013-09-15 23:44:27.668081920 80 GET text/html \n",
"2013-09-15 23:44:27.731702016 80 GET text/html \n",
"2013-09-15 23:44:28.092921856 80 GET text/html \n",
"2013-09-15 23:44:28.150300928 80 GET text/plain \n",
"2013-09-15 23:44:28.150601984 80 GET text/plain \n",
"\n",
" request_body_len \n",
"ts \n",
"2013-09-15 23:44:27.668081920 0 \n",
"2013-09-15 23:44:27.731702016 0 \n",
"2013-09-15 23:44:28.092921856 0 \n",
"2013-09-15 23:44:28.150300928 0 \n",
"2013-09-15 23:44:28.150601984 0 "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Show the dataframe with mixed feature types\n",
"zeek_df[features].head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"\n",
"## Transformers\n",
"**We'll now use a scikit-learn tranformer class to convert the Pandas DataFrame to a numpy ndarray (matrix). Yes it's awesome... I'm not sure it's Optimus Prime awesome.. but it's still pretty nice.**"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Normalizing column id.resp_p...\n",
"Normalizing column request_body_len...\n",
"(150, 12)\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/briford/.pyenv/versions/3.9.9/envs/py39/lib/python3.9/site-packages/pandas/core/arrays/categorical.py:2631: FutureWarning: The `inplace` parameter in pandas.Categorical.add_categories is deprecated and will be removed in a future version. Removing unused categories will always return a new Categorical object.\n",
" res = method(*args, **kwargs)\n"
]
},
{
"data": {
"text/plain": [
"array([[0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0.]], dtype=float32)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Use the zat DataframeToMatrix class (handles categorical data)\n",
"# You can see below it uses a heuristic to detect category data. When doing\n",
"# this for real we should explicitly convert before sending to the transformer.\n",
"to_matrix = DataFrameToMatrix()\n",
"zeek_matrix = to_matrix.fit_transform(zeek_df[features], normalize=True)\n",
"print(zeek_matrix.shape)\n",
"zeek_matrix[:1]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"IsolationForest(contamination=0.25)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Train/fit and Predict anomalous instances using the Isolation Forest model\n",
"odd_clf = IsolationForest(contamination=0.25) # Marking 25% odd\n",
"odd_clf.fit(zeek_matrix)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(32, 4)\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
id.resp_p
\n",
"
method
\n",
"
resp_mime_types
\n",
"
request_body_len
\n",
"
\n",
"
\n",
"
ts
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
2013-09-15 23:44:47.464161024
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:47.464161024
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:49.221977856
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:50.805350144
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:51.404619008
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id.resp_p method resp_mime_types \\\n",
"ts \n",
"2013-09-15 23:44:47.464161024 80 GET application/x-dosexec \n",
"2013-09-15 23:44:47.464161024 80 GET application/x-dosexec \n",
"2013-09-15 23:44:49.221977856 80 GET application/x-dosexec \n",
"2013-09-15 23:44:50.805350144 80 GET application/x-dosexec \n",
"2013-09-15 23:44:51.404619008 80 GET application/x-dosexec \n",
"\n",
" request_body_len \n",
"ts \n",
"2013-09-15 23:44:47.464161024 0 \n",
"2013-09-15 23:44:47.464161024 0 \n",
"2013-09-15 23:44:49.221977856 0 \n",
"2013-09-15 23:44:50.805350144 0 \n",
"2013-09-15 23:44:51.404619008 0 "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Now we create a new dataframe using the prediction from our classifier\n",
"odd_df = zeek_df[features][odd_clf.predict(zeek_matrix) == -1]\n",
"print(odd_df.shape)\n",
"odd_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Normalizing column id.resp_p...\n",
"Normalizing column request_body_len...\n"
]
}
],
"source": [
"# Now we're going to explore our odd dataframe with help from KMeans and PCA algorithms\n",
"odd_matrix = to_matrix.fit_transform(odd_df)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
id.resp_p
\n",
"
method
\n",
"
resp_mime_types
\n",
"
request_body_len
\n",
"
x
\n",
"
y
\n",
"
cluster
\n",
"
\n",
"
\n",
"
ts
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
2013-09-15 23:44:47.464161024
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
1.112839
\n",
"
-0.615775
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:47.464161024
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
1.112838
\n",
"
-0.615774
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:49.221977856
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
1.112838
\n",
"
-0.615774
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:50.805350144
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
1.112838
\n",
"
-0.615774
\n",
"
0
\n",
"
\n",
"
\n",
"
2013-09-15 23:44:51.404619008
\n",
"
80
\n",
"
GET
\n",
"
application/x-dosexec
\n",
"
0
\n",
"
1.112838
\n",
"
-0.615774
\n",
"
0
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id.resp_p method resp_mime_types \\\n",
"ts \n",
"2013-09-15 23:44:47.464161024 80 GET application/x-dosexec \n",
"2013-09-15 23:44:47.464161024 80 GET application/x-dosexec \n",
"2013-09-15 23:44:49.221977856 80 GET application/x-dosexec \n",
"2013-09-15 23:44:50.805350144 80 GET application/x-dosexec \n",
"2013-09-15 23:44:51.404619008 80 GET application/x-dosexec \n",
"\n",
" request_body_len x y cluster \n",
"ts \n",
"2013-09-15 23:44:47.464161024 0 1.112839 -0.615775 0 \n",
"2013-09-15 23:44:47.464161024 0 1.112838 -0.615774 0 \n",
"2013-09-15 23:44:49.221977856 0 1.112838 -0.615774 0 \n",
"2013-09-15 23:44:50.805350144 0 1.112838 -0.615774 0 \n",
"2013-09-15 23:44:51.404619008 0 1.112838 -0.615774 0 "
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Just some simple stuff for this example, KMeans and PCA\n",
"kmeans = KMeans(n_clusters=4).fit_predict(odd_matrix) # Change this to 3/5 for fun\n",
"pca = PCA(n_components=3).fit_transform(odd_matrix)\n",
"\n",
"# Now we can put our ML results back onto our dataframe!\n",
"odd_df['x'] = pca[:, 0] # PCA X Column\n",
"odd_df['y'] = pca[:, 1] # PCA Y Column\n",
"odd_df['cluster'] = kmeans\n",
"odd_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# Plotting defaults\n",
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"plt.rcParams['font.size'] = 14.0\n",
"plt.rcParams['figure.figsize'] = 15.0, 6.0\n",
"\n",
"# Helper method for scatter/beeswarm plot\n",
"def jitter(arr):\n",
" stdev = .02*(max(arr)-min(arr))\n",
" return arr + np.random.randn(len(arr)) * stdev"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"