Как сделать нормальное распределение в питоне

Обновлено: 06.07.2024

Всякий раз, когда мы думаем о машинном обучении, первое, что приходит на ум, — это набор данных. Хотя существует множество наборов данных, которые вы можете найти на таких веб-сайтах, как Kaggle, иногда бывает полезно извлечь данные самостоятельно и сгенерировать собственный набор данных. Генерация собственного набора данных дает вам больший контроль над данными и позволяет обучать вашу модель машинного обучения.

В этой статье мы создадим случайные наборы данных, используя библиотеку Numpy в Python.

Библиотеки необходимы:

Нормальное распределение:

В теории вероятностей нормальное или гауссовское распределение является очень распространенным непрерывным распределением вероятностей, симметричным относительно среднего значения, показывающим, что данные вблизи среднего встречаются чаще, чем данные, далекие от среднего. Нормальные распределения используются в статистике и часто используются для представления вещественных случайных величин.

Нормальное распределение является наиболее распространенным типом распределения в статистическом анализе. Стандартное нормальное распределение имеет два параметра: среднее значение и стандартное отклонение. Среднее значение является центральной тенденцией распределения. Стандартное отклонение является мерой изменчивости. Он определяет ширину нормального распределения. Стандартное отклонение определяет, как далеко от среднего значения имеют тенденцию падать. Он представляет типичное расстояние между наблюдениями и средним. он соответствует многим природным явлениям, например, высота, кровяное давление, погрешность измерения и показатели IQ соответствуют нормальному распределению.


График нормального распределения:

Пример:

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

X = np.random.normal(mu, sigma, ( 395 , 1 ))

Y = np.random.normal(mu * 2 , sigma * 3 , ( 395 , 1 ))

plt.scatter(X, Y, color = 'g' )


Выход :

Давайте посмотрим на лучший пример.

Мы сгенерируем набор данных с 4 столбцами. Каждый столбец в наборе данных представляет объект. 5-й столбец набора данных является меткой вывода. Это колеблется между 0-3. Этот набор данных может использоваться для обучения классификатора, такого как классификатор логистической регрессии, классификатор нейронной сети, машины опорных векторов и т. Д.

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

point1 = abs (np.random.normal( 1 , 12 , 100 ))

point2 = abs (np.random.normal( 2 , 8 , 100 ))

point3 = abs (np.random.normal( 3 , 2 , 100 ))

point4 = abs (np.random.normal( 10 , 15 , 100 ))

x = np.c_[point1, point2, point3, point4]

y = [ int (np.random.randint( 0 , 4 )) for i in range ( 100 )]

data[ 'col1' ] = point1

data[ 'col2' ] = point2

data[ 'col3' ] = point3

data[ 'col4' ] = point4

plt.subplot( 2 , 2 , 1 )

plt.scatter(y, point1, color = 'r' , label = 'col1' )

plt.subplot( 2 , 2 , 2 )

plt.scatter(y, point2, color = 'g' , label = 'col2' )

plt.subplot( 2 , 2 , 3 )

plt.scatter(y, point3, color = 'b' , label = 'col3' )

plt.subplot( 2 , 2 , 4 )

plt.scatter(y, point4, color = 'y' , label = 'col4' )


Выход :

Прекрасный вариантом будет строить интерактивные диаграммы с помощью plotly или включать интерактивные matplot графики в Jupyter Notebook применяя mpld3 , но не сегодня :)


Рабой средой будет Jupyter Notebook - удобная оболочка для Питона работающая в браузере. Она может быть практичнее IDE или классической интерактивной оболочки потому, что показывает графики в том же окне, на манер многих математических пакетов.

Загрузка данных и просмотр

Загрузим данные из CSV файла, где одно значение от другого отделяет запятая. В этом примере у данных отсутствует заголовок - первая строка файла с названиями полей. Поэтому укажем параметр header=None дабы данные в первой строки не принять за названия полей.

0 1307 non-null object
1 0 non-null float64
2 0 non-null float64
3 1306 non-null object
.
17 1500 non-null int64

Итак, загружено 1500 записей (строк файла), 18 полей. В первом поле 1307 записей имеют значения, во втором не одного, и так далее. Определены типы данных в некоторых полях.

1 2 4 7 8 11 13 15 16 \
count 0 0 0 0 1500.000000 0 1500 1497.000000 1497.00
mean NaN NaN NaN NaN 1.852667 NaN 2 52300.977288 2967182.03
std NaN NaN NaN NaN 0.837911 NaN 0 19574.930119 1710899.18
min NaN NaN NaN NaN 1.000000 NaN 2 33.000000 2500.00
25% NaN NaN NaN NaN 1.000000 NaN 2 46400.000000 1850000.00
50% NaN NaN NaN NaN 2.000000 NaN 2 55000.000000 2950000.00
75% NaN NaN NaN NaN 2.000000 NaN 2 62500.000000 3480000.00
max NaN NaN NaN NaN 4.000000 NaN 2 93650.000000 10500000.00

17
count 1500.000000
mean 10.500000
std 5.768204
min 1.000000
25% 5.750000
50% 10.500000
75% 15.250000
max 20.000000

Первой строкой приведены номера полей. Для некоторых из них вычислены среднее (mean), стандартное отклонение (std), максимальное и минимальные значения, перцентили.
Чтобы табличка выглядела красивее установим количество выводимых цифр для вещественных чисел:

Если там ничего нет, то добавим. Предпологаем, что у нас только два поля, ибо число заголовков должно соответствовать числу полей:

В некоторых случаях удобно анализировать данные напечатав их в красивой табличке воспользовавшись пакетом prettytable.

Создание объекта DataFrame из списков

Обработка данных

Положив именованный параметр inplace функции drop_duplicates равным True избавляемся от создания нового объекта, как это происходило выше. Теперь можно записать так

Алсо
Конвертировать текстовое представление даты в дату (объект datetime)
Предположим, что поле time состоит из записей вида 2016.08.06 18:15 .

Если необходимо, вторым параметром метода to_datetime устанавливается формат даты в исходной строке. Для вышеприведйнной строки формат должен быть описан следующим образом: %Y.%m.%d %H:%M

Графическое представление данных

Чтобы нарисовать красивые графики и диаграммы используем пакет seaborn. Это не единственный способ создавать различные диаграммы и графики (matplotlib), но, наверное, самый красивый.

Далее будем использовать plt без отдельного импорта пакета и иногда будем опускать код, добавляющий необходимые пояснения к представленным на рисунках данным:

Если в качестве рабочей среды используется ipython notebook (теперь Jupyter Notebook), то нужно включить интеграцию с matplotlib (графики в том же окне) [so] :

Отображает данные на плоскости или в пространстве. Значения случайных величин откладываются вдоль осей координат. В примере каждая запись из DataFrame представлена точкой с координатами price и price_m2.


В качестве первых двух параметров передаются названия полей (df.columns) DataFrame. Линия тренда отключается параметром fit_reg=False.


Здесь в дополнение к непосредственно данным приведён линейный коэффициент корреляции (Пирсона) - pearsonr и p-уровень значимости.

kde = False - не рисовать kernel density estimate (ядерную (?) оценку плотности вероятности), это кривая на графике выше;

Это может быть просто минимальное и максимальное значения в выборке. Второй вариант - полторы ширины ящика (расстояния между квартилями 0.25 и 0.75). Тогда точками отмечаются выбросы.



Несколько диаграмм на одном рисунке doc



Пример

После того, как данные представленны графически, проверим несколько статистических гипотез.

Проверка гипотезы о равенстве средних.
Предположим, что имеется две выборки. Например массы кошек и котов. Если вычислить средние массы самцов и самок наверняка получатся отличающиеся цифры. Даже если массы самцов и самок у данного вида животных не отличаются. Но прежде чем мы это выясним нужно ответить на вопрос. Какие различия между средними массами выборок считать значимыми, а какие нет, т.е. получившимися в силу случайности измеряемой величины.

Чтобы ответить на этот вопрос во-первых нужно учитывать, обёмы выборок. Что если выборки маленькие, и совершенно случаной в выборку самцов попали только коты-толстяки, а в выборку самок кошки без лишнего веса?)
Конечно чем больше выборка, тем меньше вероятность что туда попадут исключительно коты с нетипичной массой.
Во-вторых нужно учитывать на сколько вообще случайна масса самих кошек и котов. Если мы будем помещать в выборку кошек разной породы, то там будут самые разные массы. Стало быть если разброс масс может быть большой, то можно думать, что и средние тоже могут отличатся сильнее.

Поэтому чтобы сделать обоснованый вывод о равенстве средних нужно учесть характеричтики выборок. Для этого существуют специальные процедуры сравнения. Они называются статистическими критериями (тестами). Некоторые из них.
Одни критерии применимы для маленьких выборок, порядка единиц. Другие можно применять только для больших выборок, а третьи только для выборок распределённых по нормальному закону.

Помимо этого, одни критерии (или их варианты) применимы для зависимых, а другие для независимых выборок.
Зависимые выборки - это те где одному объекту из первой выборки соответствует обхект из второй. Стало быть выборки должны иметь один и тот же объём.
Например близнецов можно рахбить на две выборки. У каждого близнеца будет ровно один брат (или сетра) в другой выборке. Причём не любой брат, а именно его брат.
Другой пример зависимых выборок - рост людей в 20 и в 30 лет. Здесь человеку ставится в соответствие он же сам.

Для независимых выборок нельзя сказать, что именно этому объекту из первой ыборки соответствует именно из второй. Пример с кошками как раз представляет собой две независимые выборки.

Проверим гипотезу о равенстве средних используя t-критерий Стьюдента. (Притворимся что выборки имеют нормальное распределение).
Нулевая гипотеза здесь (как и во многих похожих тестах) следующая: математические ожидания равны. Если точнее, то равны именно математические ожидания генеральныз совокупностей из которых сделаны выборки. Ведь выборочные мат.ожидания мы и без критериев сравнить можем.

from scipy.stats import *

В результате нам интересно p-value. Оно здесь заметно больше всякого разумного уровня значимости (например 0.05) поэтому оснований для отклонения нулевой гипотезы нет: матожидания генеральных совокупностей равны.

Другие статистические критерии для проверки равенства средних:

Вычисление коэффициента корреляции Пирсона и проверка его значимости.
Коэффициент корреляции Пирсона (лиейный коэффициент корреляции) описывает силу линейной зависимости между двумя случайными величинами. Он принимает значения в отрезке от 1 до -1. Значение к.к. Пирсона близкое к нулю говорит об отсутствии (слабой зависимости) линейной зависимости между случайными величинами. Значение близкое по модулю к еденице, наоборот говорит о сильной линейной зависимости. Стоит отметить, что случайные величины могут быть связаны ещё и нелинейной зависимостью, тогда к.к. Пирсона здесь плохой помошник. Кроме того, вычисляя к.к. по выборке можно совершенно случайно получить то или иное значение к.к., поэтому имеет смысл оперировать ещё и степенью уверенности для этого значения. В математической статистике для этого служит p-value - вероятность получить такое или ещё более выраженное значение случайно. На практике, особенно при небольших объемах выборки нулевого p-value добится не получается, поэтому довольствуются некоторыми малыми вероятностями того, что величниа (в нашем случае к.к) получена не случайно. Обычно, в соответствии с принципом практической невозможности маловероятных событий, принимают допустимую вероятность ошибки в 0.05 или 0.01. Однако стоит обратить внимание на то, что при многократном извлечении выборки и вычислении параметра, можно получить желаемое значение параметра совершенно случайно.

В итоге имем значение к.к. r= 0.49
p-vlue = 0.000013 scipy.stats.uniforn - равномерное распределение
scipy.stats.norm - нормальное распределение
scipy.stats.t - распределение Стьюдента (t-распределение)
scipy.stats.poisson - распределение Пуассона

Эти классы имеют схожие методы для генерирования случайных значений - rvs .

Генерирование одного значения СВ распределённой по стандартному нормальному закону:
scipy.stats.norm.rvs()

Различия в вызове функции rvs для каждого подмодуля - это различия в параметрах распределений.
Например равномерное распределение (uniform) имеет два параметра определяющие минимальное и максимальное значение СВ.
Нормальное распределение имеет тоже два параметра, но это математическое ожидание и стандартное отклонение.

функция rvs имеет три параметра которые и задают параметры распределения эти параметры loc, shape, scale
какие из этих трёх параметров нужно задавать и какой смысл они имеют напиcано в документации к подмодулю

параметры указываются так:
scipy.stats.norm.rvs(loc = 12.2)
Для параметра shape приводится просто число:
scipy.stats.norm.rvs(5.72)

Пример
help( scipy.stats.norm )

The location (loc) keyword specifies the mean.
The scale (scale) keyword specifies the standard deviation.

loc - это математическое ожидание
sсale - стандартное отклонение

Отдельным параметром size задаётся количество значений СВ которые нужно сгенерировать.

Создание 100 значений нормально распределённой случайной величины с математическим лжиданием 4 и стандартным отклонением 7.

CDF (cumulative distribution function) - функция распределения случайной величины. Значение этой функции - вероятность в которой случайная величина X примет значение меньше заданного x:


На рисунке, вероятность того что случайная величина примет значении меньше 1 закрашена серым. Площадь под любой кривой распределения всегда равна еденице.

При проверке статистических гипотез или вычислении доверительных интервалов нужно вычислять значение функции распределения случайно величины. В каждом конкретной задаче случайная величина может быть распределена по какому угодно закону т.е. иметь свою форму кривой плотности вероятности.

Кроме проверки гипотез, CDF может пригодится и для вычисления вероятности того, что случайная величина примет значение лежащие в отрезке. Такая вероятность вычисляется по формуле:

В пакете scipy функции распределения имеют схожий интерфейс, у каждой можно вызвать cdf, pdf, isf функции. Приведём пакеты некоторых функции распределения из них.

Это же значение можно подсмотреть и в таблице pdf

Если обозначить площадль слева от заданной ординаты как p (закрашени область на рис. выше), то площадь справа q = 1 - p.
Получить ординату точки по значению q работа функции isf.

Графики в Pandas

Если вы только начали знакомство с датасетами или готовитесь к их публикации, визуализация данных очень важна. Pandas является популярной библиотекой для анализа данных в Python, которая предоставляет различные варианты визуализации данных с помощью метода .plot() . Даже если вы только начинаете изучение библиотеки pandas, скоро вы сможете создавать простые графики с ценной информацией о любых данных.

Содержание статьи

Темы, рассматриваемые в данном руководстве:

  • Различные типы pandas графиков и когда их лучше использовать;
  • Как получить обзор вашего набора данных с помощью гистограммы;
  • Как обнаружить корреляцию с помощью диаграммы рассеяния;
  • Как анализировать разные категории и их соотношения.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Настройка среды в Python

Лучше всего разбирать код из этого руководства в Jupyter Notebook. Таким образом, вы сразу увидите графики и сможете поэкспериментировать с ними.

Вам также понадобится рабочая среда Python, включающая библиотеку pandas. Если у вас её еще нет, то есть несколько вариантов:

  • Если вы планируете что-то масштабное, можете скачать дистрибутив Anaconda. Он довольно большой (500 MB), но с ним вы получите почти все инструменты для работы с данными;
  • Если вам подойдет минимальный набор инструментов, можете ознакомиться с разделом Installing the Miniconda Python Distribution на странице Setting Up Python for Machine Learning on Windows;
  • Если вы хотите использовать pip, тогда установите необходимые библиотеки с помощью команды pip install pandas matplotlib . Вы также можете установить Jupyter Notebook с помощью команды pip install jupyterlab ;
  • Если вам нужно просто попробовать какой либо код, то воспользуйтесь онлайн пробной версией Jupyter Notebook.

С уже настроенной средой, мы можем скачать тестовый набор данных. В данном руководстве мы проанализируем данные по специальностям выпускников колледжей, полученные в результате исследования American Community Survey 2010–2012, которое находится в общественном доступе. Работа послужила основой для гида по выбору колледжа Economic Guide To Picking A College Major, размещенного на сайте FiveThirtyEight.

Сначала скачиваем данные, для этого передаем URL для скачивания в pandas.read_csv() :

После вызова read_csv() создается DataFrame — главная структура данных, используемая в pandas.

На заметку: Можете воспользоваться данным руководством, даже если вы не знакомы со структурой DataFrame.

При наличии структуры DataFrame вы можете просмотреть данные. Сначала нужно настроить параметр display.max.columns , чтобы убедиться, что pandas не скрывает никакие столбцы. Затем вы можете просмотреть первые несколько строк данных с помощью метод .head():

Только что вы отобразили первые пять строк структуры DataFrame из переменной df , используя метод .head() . Результат выглядит следующим образом:

структура dataframe

С помощью метода .head() по умолчанию отображается только пять строк, но вы можете указать любое число строк через аргумент. К примеру, для отображения первых десяти строк, мы напишем так df.head(10) .

Создание простого Pandas графика в Python

Рассматриваемый набор данных содержит несколько столбцов, связанных с доходами выпускников по каждой специальности:

Начнем с графика, который отображает эти столбцы. Сначала вам потребуется настроить Jupyter Notebook для отображения графиков с помощью магической команды %matplotlib :

Магическая команда %matplotlib настраивает Jupyter Notebook для отображения графиков с помощью Matplotlib. По умолчанию используется стандартный графический бэкенд от Matplotlib, и ваши графики отображаются в отдельном окне.

На заметку: Вы можете изменить бэкенд Matplotlib, передав аргумент в магическую команду %matplotlib .

К примеру, бэкенд inline популярен для Jupyter Notebooks, потому что он отображает график в самом блокноте сразу под ячейкой, которая создает график:

Есть число доступных бэкендов. Для более подробной информации ознакомьтесь с руководством Rich Outputs в документации IPython.

Теперь вы готовы к созданию первого графика. Это можно сделать с помощью метода .plot() :

Метод . plot() возвращает линейный график, который содержит данные из каждой строки структуры DataFrame. Значения по оси х представляют рейтинг каждого учреждения, а значения "P25th" , "Median" и "P75th" показываются на оси у графика.

На заметку: Если вы не используете Jupyter Notebook или оболочку IPython, тогда для отображения графика вам потребуется интерфейс pyplot из matplotlib .

Стандартная оболочка Python отображает график следующим образом:

Обратите внимание, что перед вызовом plt.show() для отображения графика, нужно импортировать модуль pyplot из Matplotlib.

Фигура, созданная с помощью метода .plot() , отображается в отдельном окне и по умолчанию выглядит следующим образом:

график в python

При рассмотрении графика можно сделать следующие выводы:

  • Средний заработок уменьшается по мере уменьшения рейтинга. Это ожидаемо, потому что рейтинг определяется средним доходом;
  • У некоторых специальностей большой разрыв между 25-м и 75-м процентилями. Люди с этими степенями могут зарабатывать значительно меньше или значительно больше среднего дохода;
  • У других специальностей очень небольшой разрыв между 25-м и 75-м процентилями. Люди с такими степенями получают зарплату, очень близкую к средней.

Первый график уже дает понять, что в датасетах можно найти много интересного. У некоторых специальностей есть широкий диапазон заработков, у других он довольно узкий. Для обнаружения этих различий будет использоваться другие типы графиков.

У метода .plot() есть несколько необязательных параметров. В частности, параметр kind принимает одиннадцать различных строковых значений и определяет, какой тип графика создается:

  1. area для графиков с накоплением;
  2. bar для вертикальной гистограммы;
  3. barh для горизонтальной гистограммы;
  4. box для графиков с боксами;
  5. hexbin для шестнадцатеричных графиков;
  6. hist для гистограмм;
  7. kde для графика оценки плотности ядра;
  8. density является альтернативным названием для kde;
  9. line для линейных графиков;
  10. pie для круговых графиков;
  11. scatter для графиков рассеяния.

Тип графика по умолчанию является line . Линейные графики наподобие того, что был создан выше, дают хороший обзор данных. Их можно использовать для обнаружения общих трендов. С их помощью не получится сделать глубокий анализ, однако они могут помочь выяснить, на какую область стоит обратить внимание.

Если вы не укажите параметр для метода .plot() , она создаст линейный график с индексом по оси x и всеми числовыми столбцами по оси y . Данный тип графика подходит для наборов данных с несколькими столбцами, но для нашего набора данных по специальностям колледжа с его несколькими числовыми столбцами это выглядит довольно беспорядочно.

Теперь после создания нашего первого pandas графика можно подробнее разобрать, как именно работает метод .plot() .

Библиотека Matplotlib в Python

При вызове метода .plot() для объекта DataFrame Matplotlib незаметно создает наш график.

Чтобы убедиться в этом, воспользуемся двумя фрагментами кода. Сначала создадим график с помощью Matplotlib, используя два столбца из структуры DataFrame :

Я пытаюсь получить нормальную кривую распределения по моему центральному пределу распределения данных.

Ниже приведена реализация, которую я пробовал.

Я получаю график ниже,

enter image description here

Вы можете увидеть нормальную кривую в красном внизу.

Может кто-нибудь сказать мне, почему кривая не подходит?

4 ответа

У тебя почти было это! Сначала убедитесь, что вы строите две гистограммы на одной оси:

Чтобы вы могли построить нормальную плотность на гистограмме, вы правильно нормализовали второй график с аргументом normed=True . Однако вы также забыли нормализовать первую гистограмму ( plt.hist(avg[0:]), normed=True ).

Я также рекомендовал бы, поскольку, поскольку вы уже импортировали scipy.stats , вы также можете использовать обычный дистрибутив, который входит в этот модуль, вместо того, чтобы самому кодировать pdf.

Собрав все это вместе, мы имеем:

Что дало мне следующий сюжет:

enter image description here

Редактировать

В комментариях вы спросили:

  1. Как я выбрал 1,5 и 5,5 в np.linspace
  2. Можно ли построить нормальное ядро над ненормализованной гистограммой?

По адресу q1. Сначала я выбрал 1,5 и 5,5 на глаз. После построения гистограммы я увидел, что ячейки гистограммы выглядят в диапазоне от 1,5 до 5,5, так что это диапазон, на котором мы хотели бы построить нормальное распределение.

Более программный способ выбора этого диапазона был бы:

Что касается вопроса 2. Да, мы можем достичь того, что вы хотите. Однако вы должны знать, что мы больше не будем строить функцию плотности вероятности .

После удаления аргумента normed=True при построении гистограммы:

Это дало мне следующий сюжет:

Я только что уменьшил гистограмму среднего списка.

enter image description here

Логика кажется правильной.

Проблема с показом данных.

Попробуйте нормализовать первую гистограмму с помощью normed=true и получить равные ячейки для обеих гистограмм. как 20 бункеров.

Бросок игральных костей - это случай равномерного распределения. Вероятность появления любого числа от 1 до 6 составляет 1/6. Таким образом, среднее значение и стандартное отклонение определяются как

enter image description here

Теперь CLT говорит, что для достаточно большого значения n, равного 10 в коде, значение pdf среднего значения для n бросков будет приближаться к нормальному распределению со средним значением 3,5 и стандартным отклонением 1,7078 / sqrt (10).

Читайте также: