Продолжение рассказа о прогнозировании цен на бриллианты с использованием машинного обучения
Этот пост является скорее продолжением истории Прогнозирование цены бриллиантов с помощью машинного обучения.
В первом посте заложены основы алгоритмов регрессии машинного обучения для прогнозирования цены дорогостоящего предмета с использованием общедоступной базы данных примерно из 54 000 бриллиантов на Kaggle.
В этом конкретном посте рассказывается о загрузке данных из PriceScope и CaratLane и их использовании для прогнозирования цен на бриллианты.
Я загрузил данные примерно о 1500 бриллиантах для собственного обучения, а не для каких-либо коммерческих целей. Данные доступны в открытом доступе на сайте pricescope.com и доступны для просмотра и загрузки любым пользователем.
df = pd.read_csv("pricescope1.csv") df.drop(’Unnamed: 0’, axis=1, inplace=True) display(df.head(3))
p.s. все функции, вызываемые в коде, таком как convertfeatures2log()
в этом посте, либо определены/описаны здесь, либо в моем предыдущем посте.
Предварительная обработка данных
Теперь выполняем все необходимые действия по обработке данных, как и раньше.
Конвертировать цену в долларах в целые числа
Как мы видим, цены в наборе данных pricescope имеют тип данных currency, т.е. цены показаны в долларах с разделителями тысяч. Поскольку алгоритму машинного обучения нужны числовые данные, нам нужно будет преобразовать долларовые значения в целые числа. Способ делаем следующим образом.
- Замените $ пробелом, используя регулярное выражение
- Преобразовать в int с помощью astype()
- Преобразование массива/серии в фрейм данных с помощью pd.DataFrame
priceint=pd.DataFrame(df[’price’].replace(’[\$,]’, '’, regex=True).astype(int)) df.drop([’price’], axis=1, inplace=True) df[’price’] = priceint[’price’].values
Проверьте, присутствуют ли нулевые значения — так же, как мы делали ранее.
df.isnull().sum()
Обратите внимание, что у Flouroscence пустые значения. Давайте посмотрим, сколько строк имеет пустой Flouroscence, и избавимся от этих данных, если пустые значения для строк меньше 0,5% от общего числа строк.
df[‘flr’].isnull().sum() / len(df[‘flr’]) *100
Выход: 0.4240282685512367
Мы видим, что нулевые значения относятся к менее чем 0,5% данных. Итак, давайте удалим эти строки.
indexnames = df[df[’flr’].isnull()].index df.drop(axis=0,index=indexnames,inplace=True)
Теперь проверьте, есть ли ожидаемые типы данных во всех столбцах, используя ту же функцию, что и ранее.
df.info()
Результат выглядит следующим образом:
<class 'pandas.core.frame.DataFrame'> Int64Index: 1409 entries, 6 to 1414 Data columns (total 12 columns): carat 1409 non-null float64 cut 1409 non-null object color 1409 non-null object clarity 1409 non-null object depth 1409 non-null object table 1409 non-null object lab 1409 non-null object sym 1409 non-null object pol 1409 non-null object flr 1409 non-null object hna 1409 non-null object price 1409 non-null int32 dtypes: float64(1), int32(1), object(10) memory usage: 137.6+ KB
Мы видим, что глубина и таблица, единственные две непрерывные функции, кроме карата, являются типом данных объекта, тогда как они должны были быть плавающими или целыми. Это означает, что присутствуют некоторые строковые значения. Давайте рассмотрим и преобразуем в числовой
lenT = len([x for x in df['table'] if not x.isnumeric()]) / len(df['table'])*100 print('Percent of non-numeric data in Table -->', lenT) lenD = len([x for x in df['depth'] if not x.isnumeric()]) / len(df['depth'])*100 print('Percent of non-numeric data in Depth -->', lenD)
Процент нечисловых данных в таблице → 5,25195173882186
Процент нечисловых данных в глубине → 92,902767920511
Теперь давайте посмотрим, являются ли они числами с плавающей запятой, хранящимися в виде строк, или какими-то бессмысленными значениями.
Создайте функцию removenotnum()
и вызовите ее, чтобы увидеть значения
Результат:
all rubish values --> {'-'} Percent of identified rubbish data in Table --> 0.07097232079488999 all rubish values --> {'-'} Percent of identified rubbish data in Depth --> 0.07097232079488999
Похоже, что только один тип ненужного символа «-» хранится в 0,5% данных. Поскольку это крошечная часть всего набора данных, мы можем сейчас безопасно удалить все эти строки. Удалите строки с мусорными значениями для таблицы и глубины.
indexnames = df[(df[‘table’] == ‘-’) | (df[‘depth’] == ‘-’)].index df.drop(axis=0,index=indexnames,inplace=True)
Теперь преобразуйте тип данных объекта table и depth в число с плавающей запятой.
df[‘table’] = df[‘table’].astype(float) df[‘depth’] = df[‘depth’].astype(float)
Затем мы строим парный график цены и 4 Cs.
sns.pairplot(df, x_vars=[‘carat’, ‘cut’, ‘clarity’, ‘color’], y_vars = [‘price’]) plt.show()
Теперь запустите convert_catg()
function в наборе данных pricescope, чтобы преобразовать категориальные столбцы в числовые столбцы. Вывод будет следующим:
Теперь мы проверяем любые выбросы, вызывая функцию dfboxplot()
для построения коробчатых диаграмм всех свойств. Мы снова удалим строки, содержащие данные о выбросах для любого свойства, если такие строки составляют менее 0,5% набора данных.
Поскольку я загрузил данные с работающего в настоящее время веб-сайта, маловероятно, что мы получим какие-либо нестандартные данные.
Как и ожидалось, мы видим, что выбросов нет.
Теперь мы преобразуем значения всех непрерывных признаков («карат», «глубина», «таблица», «цена») в логарифмические путем вызова convertfeatures2log()
для лучшего использования алгоритмами машинного обучения.
Запуск алгоритмов машинного обучения
Сначала мы устанавливаем X и y, как и раньше.
X_df = df.drop([‘price’], axis=1) y_df = df[[‘price’]]
Теперь мы видим корреляцию между ценой и всеми другими атрибутами следующим образом:
Снова Train Test Split:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_df, y_df, test_size=0.3, random_state=42)
Линейная модель
Сначала мы запускаем модель линейной регрессии.
from sklearn.linear_model import LinearRegression reg_all = LinearRegression() reg_all.fit(X_train,y_train) y_pred=reg_all.predict(X_test)
Его график и диаграмма рассеяния показывают, что этот простой алгоритм линейной регрессии является действительно хорошим алгоритмом прогнозирования.
Однако метрики говорят о другом:
MAE: 0.11652136924155168 MSE: 0.02292105733384392 RMSE: 0.15139701890672722
Случайный лес
Все знают, и мы только что проверили прогнозирование цен на бриллианты из набора данных Kaggle, что Random Forest — надежный алгоритм.
MAE: 0.06791631018129721 MSE: 0.010798208786551588 RMSE: 0.10391443011705154
Нейронная сеть
Мы настраиваем определение базовой модели и предоставляем различное количество слоев и функций активации.
Обратите внимание, что мы предоставляем первому слою 11 входных объектов и 18 скрытых узлов. Для следующего слоя ожидается 12 выходных узлов. Я попробовал несколько комбинаций, и они оказались приемлемыми.
Результат для ANN после запуска функций KerasRegressor
, KFold
и cross_val_score
, как мы делали ранее, немного лучше, чем линейная регрессия, но не так хорош, как случайный лес.
Чтобы рассчитать правильную цену бриллианта, который вы видите в алмазном районе, вы вызываете функцию прогнозирования этой модели следующим образом. Рассматриваемый бриллиант – это этот.
newdiamond = [‘0.3’, ‘Premium’, ‘ G’, ‘VS1’, 57, 516, ‘GIA’, ‘X’, ‘X’, ’N’, ‘N’] rf.predict(newdiamond)
использованная литература
Для этого конкретного поста я сослался на несколько веб-сайтов, включая Beyond4Cs, Мастерство машинного обучения и другие несколько постов и веб-сайтов в Интернете.
Обо мне
Я работаю в области ИТ-проектов Инвестиционного банка. У меня есть 15-летний опыт создания готовых к производству приложений для фронт-офисной торговли и последние 3 года в области машинного обучения, NLP, NER, обнаружения аномалий и т. д.
За время своей карьеры в сфере искусственного интеллекта и машинного обучения я изучал различные посты в СМИ/хакернун/кднуггетс; проходил различные курсы на Coursera, Udemy, edX; просмотрел множество видеороликов на YouTube.
Я считаю, что получение всех этих знаний придаст вам уверенности в себе и подготовит к следующему жизненному вызову.
Однако даже за годы обучения и опыта (проектов) вряд ли можно знать хотя бы 1% об области AI ML.
Возможно, она столь же обширна, как Вселенная, постоянно развивается и исследуется людьми даже на уровень верхушки айсберга.
Не стесняйтесь связаться со мной в LinkedIn или подписаться на меня в Medium.