2.2 MiB
Для выполнения данной практической работы предлагается проанализировать набор данных Data of rotary machine defects , который доступен для скачивания на Kaggle. Этот набор данных представляет собой результаты эксперимента по выявлению дефектов в подшипниковых узлах жидкостного трения. Время эксперимента 10 мин. Частота получения данных о колебаниях ротора 1000 сиг/сек. Частота съема данных о температуре 1 сиг/сек. Первая цифра в названии файла указывает на номер эксперимента, а вторая на класс дефекта. Соответствие номера дефекта и его вида: ‒ 1 - нет дефектов, ‒ 2 - несоосность в муфте, ‒ 3 - наличие дисбаланса, ‒ 4 - втулка с дефектами.
Каждый столбец соответствует определенному параметру, в строках распо-ложены значения показаний с датчиков в каждый временной промежуток време-ни. Данные датчиков температуры продублированы для каждой секунды, для упрощения соотношения данных.
Init¶
Зависит от используемой Вами среды.
# Install a pip package in the current Jupyter kernel import sys !{sys.executable} -m pip install numpy scipy scikit-learn jupyter matplotlib pandas seaborn %matplotlib inline import zipfile import os import numpy as np import seaborn as sns import pandas as pd import matplotlib.pyplot as plt from sklearn import preprocessing from IPython.display import Image from matplotlib.patches import Ellipse, PathPatch, Arc, Polygon, Wedge plt.rcParams['figure.dpi'] = 300
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/ Requirement already satisfied: numpy in /usr/local/lib/python3.8/dist-packages (1.21.6) Requirement already satisfied: scipy in /usr/local/lib/python3.8/dist-packages (1.7.3) Requirement already satisfied: scikit-learn in /usr/local/lib/python3.8/dist-packages (1.0.2) Collecting jupyter Downloading jupyter-1.0.0-py2.py3-none-any.whl (2.7 kB) Requirement already satisfied: matplotlib in /usr/local/lib/python3.8/dist-packages (3.2.2) Requirement already satisfied: pandas in /usr/local/lib/python3.8/dist-packages (1.3.5) Requirement already satisfied: seaborn in /usr/local/lib/python3.8/dist-packages (0.11.2) Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.8/dist-packages (from scikit-learn) (3.1.0) Requirement already satisfied: joblib>=0.11 in /usr/local/lib/python3.8/dist-packages (from scikit-learn) (1.2.0) Requirement already satisfied: notebook in /usr/local/lib/python3.8/dist-packages (from jupyter) (5.7.16) Collecting qtconsole Downloading qtconsole-5.4.0-py3-none-any.whl (121 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 121.0/121.0 KB 2.9 MB/s eta 0:00:00 Requirement already satisfied: jupyter-console in /usr/local/lib/python3.8/dist-packages (from jupyter) (6.1.0) Requirement already satisfied: nbconvert in /usr/local/lib/python3.8/dist-packages (from jupyter) (5.6.1) Requirement already satisfied: ipywidgets in /usr/local/lib/python3.8/dist-packages (from jupyter) (7.7.1) Requirement already satisfied: ipykernel in /usr/local/lib/python3.8/dist-packages (from jupyter) (5.3.4) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.8/dist-packages (from matplotlib) (0.11.0) Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.8/dist-packages (from matplotlib) (3.0.9) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.8/dist-packages (from matplotlib) (1.4.4) Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.8/dist-packages (from matplotlib) (2.8.2) Requirement already satisfied: pytz>=2017.3 in /usr/local/lib/python3.8/dist-packages (from pandas) (2022.7.1) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.8/dist-packages (from python-dateutil>=2.1->matplotlib) (1.15.0) Requirement already satisfied: ipython>=5.0.0 in /usr/local/lib/python3.8/dist-packages (from ipykernel->jupyter) (7.9.0) Requirement already satisfied: jupyter-client in /usr/local/lib/python3.8/dist-packages (from ipykernel->jupyter) (6.1.12) Requirement already satisfied: traitlets>=4.1.0 in /usr/local/lib/python3.8/dist-packages (from ipykernel->jupyter) (5.7.1) Requirement already satisfied: tornado>=4.2 in /usr/local/lib/python3.8/dist-packages (from ipykernel->jupyter) (6.0.4) Requirement already satisfied: ipython-genutils~=0.2.0 in /usr/local/lib/python3.8/dist-packages (from ipywidgets->jupyter) (0.2.0) Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.8/dist-packages (from ipywidgets->jupyter) (3.6.1) Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.8/dist-packages (from ipywidgets->jupyter) (3.0.5) Requirement already satisfied: pygments in /usr/local/lib/python3.8/dist-packages (from jupyter-console->jupyter) (2.6.1) Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.8/dist-packages (from jupyter-console->jupyter) (2.0.10) Requirement already satisfied: jupyter-core in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (5.2.0) Requirement already satisfied: testpath in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (0.6.0) Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (1.5.0) Requirement already satisfied: defusedxml in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (0.7.1) Requirement already satisfied: jinja2>=2.4 in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (2.11.3) Requirement already satisfied: nbformat>=4.4 in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (5.7.3) Requirement already satisfied: entrypoints>=0.2.2 in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (0.4) Requirement already satisfied: bleach in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (6.0.0) Requirement already satisfied: mistune<2,>=0.8.1 in /usr/local/lib/python3.8/dist-packages (from nbconvert->jupyter) (0.8.4) Requirement already satisfied: terminado>=0.8.1 in /usr/local/lib/python3.8/dist-packages (from notebook->jupyter) (0.13.3) Requirement already satisfied: Send2Trash in /usr/local/lib/python3.8/dist-packages (from notebook->jupyter) (1.8.0) Requirement already satisfied: prometheus-client in /usr/local/lib/python3.8/dist-packages (from notebook->jupyter) (0.16.0) Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.8/dist-packages (from notebook->jupyter) (23.2.1) Collecting qtpy>=2.0.1 Downloading QtPy-2.3.0-py3-none-any.whl (83 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 83.6/83.6 KB 5.7 MB/s eta 0:00:00 Requirement already satisfied: pexpect in /usr/local/lib/python3.8/dist-packages (from ipython>=5.0.0->ipykernel->jupyter) (4.8.0) Requirement already satisfied: pickleshare in /usr/local/lib/python3.8/dist-packages (from ipython>=5.0.0->ipykernel->jupyter) (0.7.5) Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.8/dist-packages (from ipython>=5.0.0->ipykernel->jupyter) (57.4.0) Collecting jedi>=0.10 Downloading jedi-0.18.2-py2.py3-none-any.whl (1.6 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 25.9 MB/s eta 0:00:00 Requirement already satisfied: decorator in /usr/local/lib/python3.8/dist-packages (from ipython>=5.0.0->ipykernel->jupyter) (4.4.2) Requirement already satisfied: backcall in /usr/local/lib/python3.8/dist-packages (from ipython>=5.0.0->ipykernel->jupyter) (0.2.0) Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.8/dist-packages (from jinja2>=2.4->nbconvert->jupyter) (2.0.1) Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.8/dist-packages (from jupyter-core->nbconvert->jupyter) (3.0.0) Requirement already satisfied: fastjsonschema in /usr/local/lib/python3.8/dist-packages (from nbformat>=4.4->nbconvert->jupyter) (2.16.2) Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.8/dist-packages (from nbformat>=4.4->nbconvert->jupyter) (4.3.3) Requirement already satisfied: wcwidth in /usr/local/lib/python3.8/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->jupyter-console->jupyter) (0.2.6) Requirement already satisfied: packaging in /usr/local/lib/python3.8/dist-packages (from qtpy>=2.0.1->qtconsole->jupyter) (23.0) Requirement already satisfied: ptyprocess in /usr/local/lib/python3.8/dist-packages (from terminado>=0.8.1->notebook->jupyter) (0.7.0) Requirement already satisfied: webencodings in /usr/local/lib/python3.8/dist-packages (from bleach->nbconvert->jupyter) (0.5.1) Requirement already satisfied: parso<0.9.0,>=0.8.0 in /usr/local/lib/python3.8/dist-packages (from jedi>=0.10->ipython>=5.0.0->ipykernel->jupyter) (0.8.3) Requirement already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in /usr/local/lib/python3.8/dist-packages (from jsonschema>=2.6->nbformat>=4.4->nbconvert->jupyter) (0.19.3) Requirement already satisfied: importlib-resources>=1.4.0 in /usr/local/lib/python3.8/dist-packages (from jsonschema>=2.6->nbformat>=4.4->nbconvert->jupyter) (5.10.2) Requirement already satisfied: attrs>=17.4.0 in /usr/local/lib/python3.8/dist-packages (from jsonschema>=2.6->nbformat>=4.4->nbconvert->jupyter) (22.2.0) Requirement already satisfied: zipp>=3.1.0 in /usr/local/lib/python3.8/dist-packages (from importlib-resources>=1.4.0->jsonschema>=2.6->nbformat>=4.4->nbconvert->jupyter) (3.12.1) Installing collected packages: qtpy, jedi, qtconsole, jupyter Successfully installed jedi-0.18.2 jupyter-1.0.0 qtconsole-5.4.0 qtpy-2.3.0
# https://www.kaggle.com/datasets/kazakovyurii/data-of-rotary-machine-defects dataset_path = "dataset" zip_path = "archive.zip" # if not os.path.exists(dataset_path): # os.mkdir(dataset_path) # with zipfile.ZipFile(zip_path, "r") as zip_ref: # zip_ref.extractall("dataset")
Загрузка данных¶
About data¶
Field | Units | Description |
---|---|---|
Fluctuations_X_in_the_left_bearing | [V] | Horizontal horizons in the left bearing, in Volts |
Fluctuations_Y_in_the_left_bearing | [V] | Vertical oscillations in the left bearing, in Volts |
Fluctuations_X_in_the_right_bearing | [V] | Horizontal vibrations in the right bearing, in Volts |
Fluctuations_Y_in_the_right_bearing | [V] | Vertical vibrations in the right bearing bearing, in Volts |
Fluctuations_X_in_the_left_bearing_smooth | [V] | Horizontal vibrations in the left bearing, taking into account smoothing, in Volts |
Fluctuations_Y_in_the_left_bearing_smooth | [V] | Vertical vibrations in the left bearing, taking into account smoothing, in Volts |
Fluctuations_X_in_the_right_bearing_smooth | [V] | Horizontal vibrations in the right bearing, taking into account smoothing, in Volts |
Fluctuations_Y_in_the_right_bearing_smooth | [V] | Vertical vibrations in the right bearing bearing, taking into account smoothing, in Volts |
Temperature_in_the_left_bearing | [V] | Temperature in the left bearing, in ohms |
Temperature_in_the_right_bearing | [O] | Temperature in the right bearing, in ohms |
Извлечение данных¶
Зависит от среды разработки. Проверьте корректность путей для загрузки данных.
data = [pd.read_csv(f"/content/data_2_{i}.csv") for i in range(1, 5)] data = [d.rename(columns=lambda x: x.strip()) for d in data]
tracked_columns =[ "Fluctuations_X_in_the_left_bearing", "Fluctuations_Y_in_the_left_bearing", "Fluctuations_X_in_the_right_bearing", "Fluctuations_Y_in_the_right_bearing", "Fluctuations_X_in_the_left_bearing_smooth", "Fluctuations_Y_in_the_left_bearing_smooth", "Fluctuations_X_in_the_right_bearing_smooth", "Fluctuations_Y_in_the_right_bearing_smooth", "Temperature_in_the_left_bearing", "Temperature_in_the_right_bearing" ] data = [d[tracked_columns] for d in data]
data[0].head()
Fluctuations_X_in_the_left_bearing | Fluctuations_Y_in_the_left_bearing | Fluctuations_X_in_the_right_bearing | Fluctuations_Y_in_the_right_bearing | Fluctuations_X_in_the_left_bearing_smooth | Fluctuations_Y_in_the_left_bearing_smooth | Fluctuations_X_in_the_right_bearing_smooth | Fluctuations_Y_in_the_right_bearing_smooth | Temperature_in_the_left_bearing | Temperature_in_the_right_bearing | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 5.671 | 6.404 | 6.040 | 7.257 | 5.442 | 6.486 | 5.593 | 7.145 | 1104.633 | 1104.664 |
1 | 5.599 | 6.298 | 5.758 | 7.203 | 5.641 | 6.361 | 5.838 | 7.206 | 1104.633 | 1104.664 |
2 | 5.589 | 6.236 | 5.654 | 7.165 | 5.571 | 6.249 | 5.700 | 7.192 | 1104.633 | 1104.664 |
3 | 5.489 | 6.414 | 5.632 | 7.319 | 5.471 | 6.294 | 5.645 | 7.219 | 1104.633 | 1104.664 |
4 | 5.623 | 6.455 | 5.791 | 7.310 | 5.592 | 6.440 | 5.716 | 7.349 | 1104.633 | 1104.664 |
scaled_data = data for i, df in enumerate(data): scaled_temp = pd.DataFrame( preprocessing.MinMaxScaler().fit_transform(df), columns=df.columns ) scaled_data[i]=scaled_temp scaled_data[0].head() data = scaled_data
Вычисление корреляции между признаками в данных¶
def get_empty_columns_names(df): empty = [col for col in df.columns if (df[col].isnull().all() or df[col].isna().all())] return empty
def heatmap(df, ax, title): corr = df.corr() # Omit pairs with weak correlation, try to experiments with this setting df_corr = corr[((corr >= .6) | (corr <= -.6))] #print("Empty columns:", get_empty_columns_names(df_corr)) mask = np.triu(np.ones_like(corr)) sns.heatmap( df_corr, cbar=False, mask=mask, ax=ax, annot=True, cmap='coolwarm', vmin=-1, vmax=1, ) ax.title.set_text(title) ax.tick_params( top=False, bottom=False, left=False, right=False, )
fig, ax = plt.subplots( nrows=2, ncols=2, sharey=True, sharex=True, figsize=(20, 20), constrained_layout=True ) axes = ax.flatten() for i, df in enumerate(data): heatmap(df, axes[i], f"Experiment {i + 1}") plt.savefig("heatmaps.png", bbox_inches="tight") plt.close()
img = Image("heatmaps.png") img
Интересно увидеть, что в случае экспериментов с аномалиями появляется больше линейных связей между параметрами. Попробуйте поменять пороги для визуализации коэффициентов корреляции, вы сможете увидеть, что некоторые связи появляются, а некоторые исчезают, именно это может служить основанием для построения схемы кодирования.
Реализация лиц Чернова¶
За основу взята реализация, предложенная тут и доработанная магистром СПбГЭТУ "ЛЭТИ" В. Киселевой. Вы можете разработать собственный дизайн лица
Схема кодирования¶
Field | Face feature |
---|---|
Fluctuation_X_in_the_right_bearing_smooth | Hair color |
Fluctuations_X_in_the_left_bearing | Skin color |
Fluctuations_Y_in_the_right_bearing_smooth | Hair length at the left side |
Fluctuations_Y_in_the_left_bearing_smooth | Hair length at the right side |
Fluctuations_Y_in_the_right_bearing | Curvature of the eyebrow at the left side |
Fluctuations_Y_in_the_left_bearing | Curvature of the eyebrow at the right side |
Fluctuations_X_in_the_right_bearing | Height of the eye at the left side |
Fluctuations_X_in_the_left_bearing_smooth | Height of the eye at the right side |
Not used | Width of the nose |
Not used | Width of the mouth |
Реализация¶
Расчет средних показателей экспериментов (для их дальнейшей визуализации)¶
mean_data = [] for i, df in enumerate(data): mean_data.append([*df.mean().tolist()])
Reindex dataframe to fit properties order¶
mean_df = pd.DataFrame(mean_data, columns=tracked_columns) mean_df.to_csv('mean_df1.csv', index=False) reindexed_columns = [ "Fluctuations_X_in_the_right_bearing_smooth", #цвет волос "Fluctuations_X_in_the_left_bearing", # цвет лица "Fluctuations_Y_in_the_right_bearing_smooth",#+ длина волос слева "Fluctuations_Y_in_the_left_bearing_smooth", #+ длина волос справа "Fluctuations_Y_in_the_right_bearing", #брови слева "Fluctuations_Y_in_the_left_bearing", # брови справа "Fluctuations_X_in_the_right_bearing", # глаза слева "Fluctuations_X_in_the_left_bearing_smooth", #глаза справа # "Fluctuations_Y_in_the_left_bearing_smooth", # "Fluctuations_Y_in_the_right_bearing_smooth", ] mean_df = mean_df.reindex(columns=reindexed_columns) mean_df.to_csv('mean_df2.csv', index=False)
Определение класса лиц Чернова¶
class ChernoffFaces: DATA = { "HAIR_COLOR": None, "SKIN_COLOR": None, "HAIR_LEFT": None, "HAIR_RIGHT": None, "EYEBROW_CURVATURE_LEFT": None, "EYEBROW_CURVATURE_RIGHT": None, "EYE_HEIGHT_LEFT": None, "EYE_HEIGHT_RIGHT": None, "PUPIL_SIZE": 0.2, "NOSE_WIDTH": None, "MOUTH_HEIGHT": 0.2, "MOUTH_WIDTH": None, } DYNAMIC_PARAMETERS = [ "HAIR_COLOR", "SKIN_COLOR", "HAIR_LEFT", "HAIR_RIGHT", "EYEBROW_CURVATURE_LEFT", "EYEBROW_CURVATURE_RIGHT", "EYE_HEIGHT_LEFT", "EYE_HEIGHT_RIGHT", # "NOSE_WIDTH", # "MOUTH_WIDTH", ] def __init__(self, df, labels=None, filename='faces'): if not labels: self.labels = df.iloc[:,0].values df = df[df.columns.drop(df.columns[0])] self.data = df for index, key in enumerate(self.DYNAMIC_PARAMETERS): self.DATA[key] = self.data[self.data.columns[index % len(self.data.columns)]].values.tolist() self.filename = filename def render_face(self, ax, title='', index=None): height, width = ax.bbox.height, ax.bbox.width self.draw_hair(ax, index, width, height) self.draw_face(ax, index, width, height) self.draw_l_brow(ax, index) self.draw_r_brow(ax, index) self.draw_l_eye(ax, index) self.draw_r_eye(ax, index) # self.draw_nose(ax, index) # self.draw_mouth(ax, index) ax.title.set_text(title) ax.axis('off') ax.autoscale() def draw_hair(self, ax, index, width, height): hair_width = width hair_height = height colour = plt.cm.coolwarm(self.DATA["HAIR_COLOR"][index]) #настройка цветов trapeze = Polygon( xy=[ [0, hair_height * 0.5 * (1 - self.DATA["HAIR_LEFT"][index])], [0, hair_height * 0.5], [hair_width, hair_height * 0.5], [hair_width, hair_height * 0.5 * (1 - self.DATA["HAIR_RIGHT"][index])], ], fc=colour ) ax.add_patch(trapeze) top = Wedge( center=[hair_width / 2, hair_height * 0.5 - 1], r=hair_width / 2, theta1=0, theta2=180, edgecolor='none', fc=colour, ) ax.add_patch(top) def draw_face(self, ax, index, width, height): face_width = width * 2/3 face_height = height * 1/2 self.UNIT_WIDTH = face_width / 7 self.UNIT_HEIGHT = face_height / 7 self.FACE_CENTER = [width / 2, height / 2] colour = plt.cm.RdBu(self.DATA["SKIN_COLOR"][index]) #настройка цветов ellipse = Ellipse( xy=self.FACE_CENTER, width=face_width, height=face_height, edgecolor='black', fc=colour, lw=2 ) ax.add_patch(ellipse) def draw_l_brow(self, ax, index): brow_width = self.UNIT_WIDTH * 1.5 brow_height = self.UNIT_HEIGHT * self.DATA["EYEBROW_CURVATURE_LEFT"][index] if brow_height == 0: brow_height = 0.001 brow_l_center = [sum(i) for i in zip(*[ self.FACE_CENTER, [brow_width, self.UNIT_HEIGHT * 1.1] ])] brow_l = Arc( xy=brow_l_center, width=brow_width, height=brow_height, theta1=0, theta2=180, edgecolor='black', fc='None', lw=2 ) ax.add_patch(brow_l) def draw_r_brow(self, ax, index): brow_width = self.UNIT_WIDTH * 1.5 brow_height = self.UNIT_HEIGHT * self.DATA["EYEBROW_CURVATURE_RIGHT"][index] if brow_height == 0: brow_height = 0.001 brow_r_center = [sum(i) for i in zip(*[ self.FACE_CENTER, [-brow_width, self.UNIT_HEIGHT * 1.1] ])] brow_r = Arc( xy=brow_r_center, width=brow_width, height=brow_height, theta1=0, theta2=180, edgecolor='black', fc='None', lw=2 ) ax.add_patch(brow_r) def draw_l_eye(self, ax, index): eye_width = self.UNIT_WIDTH * 1.5 eye_height = self.UNIT_HEIGHT * self.DATA["EYE_HEIGHT_LEFT"][index] if eye_height == 0: eye_height = 0.001 eye_l_center = [sum(i) for i in zip(*[ self.FACE_CENTER, [-eye_width, self.UNIT_HEIGHT / 2] ])] ellipse = Ellipse( xy=eye_l_center, width=eye_width, height=eye_height, edgecolor='black', fc='white', lw=1 ) ax.add_patch(ellipse) ellipse = Ellipse( xy=eye_l_center, width=eye_width / 2, height=eye_height, edgecolor='black', fc='black', lw=1 ) ax.add_patch(ellipse) def draw_r_eye(self, ax, index): eye_width = self.UNIT_WIDTH * 1.5 eye_height = self.UNIT_HEIGHT * self.DATA["EYE_HEIGHT_RIGHT"][index] if eye_height == 0: eye_height = 0.001 eye_r_center = [sum(i) for i in zip(*[ self.FACE_CENTER, [eye_width, self.UNIT_HEIGHT / 2] ])] ellipse = Ellipse( xy=eye_r_center, width=eye_width, height=eye_height, edgecolor='black', fc='white', lw=1 ) ax.add_patch(ellipse) ellipse = Ellipse( xy=eye_r_center, width=eye_width / 2, height=eye_height, edgecolor='black', fc='black', lw=1 ) ax.add_patch(ellipse) def draw_nose(self, ax, index): nose_width = self.UNIT_WIDTH * (1 - self.DATA["NOSE_WIDTH"][index]) nose_height = self.UNIT_HEIGHT pivot_left = [sum(i) for i in zip(*[ self.FACE_CENTER, [-nose_width / 2, -nose_height] ])] pivot_right = [sum(i) for i in zip(*[ self.FACE_CENTER, [nose_width / 2, -nose_height] ])] pivot_top = self.FACE_CENTER points = np.array([pivot_left, pivot_right, pivot_top]) nose = plt.Polygon( points, closed=True, lw=1, fc="black", edgecolor='black', ) ax.add_patch(nose) def draw_mouth(self, ax, index): mouth_width = self.UNIT_WIDTH * 3 * self.DATA["MOUTH_WIDTH"][index] mouth_height = self.UNIT_HEIGHT * 1.5 * self.DATA["MOUTH_HEIGHT"] mouth_center = [sum(i) for i in zip(*[ self.FACE_CENTER, [0, -self.UNIT_HEIGHT * 2] ])] ellipse = Ellipse( xy=mouth_center, width=mouth_width, height=mouth_height, edgecolor='black', fc="black", lw=1 ) ax.add_patch(ellipse) def render(self, n_cols=2, n_rows=1, figsize=(2, 2), empty_cols_ids=()): fig, ax = plt.subplots( nrows=n_rows, ncols=n_cols, figsize=figsize, sharey=True, sharex=True, constrained_layout=True, ) fig.patch.set_facecolor('white') axes = ax.flatten() for i, ax in enumerate(axes): if i in empty_cols_ids: ax.remove() if i == 0: self.render_face(ax, title=f"Reference", index=i) continue self.render_face(ax, title=f"Experiment {i}", index=i) plt.savefig(f"{self.filename}.png", bbox_inches="tight") plt.close()
Построение визуализации для экспериментов¶
reference = pd.DataFrame([(0.5 for _ in range(8))], columns=reindexed_columns) mean_df = pd.DataFrame( preprocessing.MinMaxScaler().fit_transform(mean_df.values), columns=mean_df.columns ) mean_df = pd.concat([reference, mean_df])
c = ChernoffFaces(mean_df) c.render( n_cols = 5, n_rows = 1, figsize=(30, 7), )
img = Image("faces.png") img