Добавить Автора
Публичный аккаунт WeChat:PythonНаука о данных
Знаю почти:аналитик данных Python
В последней статье мы поделились с вами небольшим проектом вводного анализа данных, анализа цен на вторичное жилье в Пекине, Ссылка выглядит следующим образом:
В этой статье будет продолжено прогнозирование моделирования интеллектуального анализа данных после предыдущего анализа данных.Эти две части составляют простой законченный проект. Объединение двух статей может достичь эффекта прогнозирования цен на подержанное жилье с помощью анализа данных и методов добычи.
Начнем с разработки функций.
разработка функций
Инжиниринг признаков включает в себя большое количество контента, включая очистку признаков, предварительную обработку, мониторинг и т. д., а предварительная обработка делится на множество методов, основанных на отдельных признаках или нескольких признаках, таких как нормализация, уменьшение размерности, выбор признаков, скрининг признаков и т. д. . Так много способов, для чего?Цель состоит в том, чтобы сделать эти функции более удобными в качестве входных данных для модели., качество обработки данных серьезно повлияет на производительность модели, а хорошая разработка признаков иногда даже важнее, чем параметры моделирования.
Ниже приведена функция проектирования данных после последнего анализа, блоггер поможет вам интерпретировать их по одному.
"""
特征工程
"""
# 移除结构类型异常值和房屋大小异常值
df = df[(df['Layout']!='叠拼别墅')&(df['Size']<1000)]
# 去掉错误数据“南北”,因为爬虫过程中一些信息位置为空,导致“Direction”的特征出现在这里,需要清除或替换
df['Renovation'] = df.loc[(df['Renovation'] != '南北'), 'Renovation']
# 由于存在个别类型错误,如简装和精装,特征值错位,故需要移除
df['Elevator'] = df.loc[(df['Elevator'] == '有电梯')|(df['Elevator'] == '无电梯'), 'Elevator']
# 填补Elevator缺失值
df.loc[(df['Floor']>6)&(df['Elevator'].isnull()), 'Elevator'] = '有电梯'
df.loc[(df['Floor']<=6)&(df['Elevator'].isnull()), 'Elevator'] = '无电梯'
# 只考虑“室”和“厅”,将其它少数“房间”和“卫”移除
df = df.loc[df['Layout'].str.extract('^\d(.*?)\d.*?') == '室']
# 提取“室”和“厅”创建新特征
df['Layout_room_num'] = df['Layout'].str.extract('(^\d).*', expand=False).astype('int64')
df['Layout_hall_num'] = df['Layout'].str.extract('^\d.*?(\d).*', expand=False).astype('int64')
# 按中位数对“Year”特征进行分箱
df['Year'] = pd.qcut(df['Year'],8).astype('object')
# 对“Direction”特征
d_list_one = ['东','西','南','北']
d_list_two = ['东西','东南','东北','西南','西北','南北']
d_list_three = ['东西南','东西北','东南北','西南北']
d_list_four = ['东西南北']
df['Direction'] = df['Direction'].apply(direct_func)
df = df.loc[(df['Direction']!='no')&(df['Direction']!='nan')]
# 根据已有特征创建新特征
df['Layout_total_num'] = df['Layout_room_num'] + df['Layout_hall_num']
df['Size_room_ratio'] = df['Size']/df['Layout_total_num']
# 删除无用特征
df = df.drop(['Layout','PerPrice','Garden'],axis=1)
# 对于object特征进行onehot编码
df,df_cat = one_hot_encoder(df)
Поскольку в предыдущей статье упоминалась некоторая очистка, блогер начинает с 17 строк кода.
Layout
Давайте сначала посмотрим, как выглядит необработанное значение функции макета.
df['Layout'].value_counts()
Все видели, что собственные значения не так идеальны, как представлялось. Существует два формата данных, один из них"xx室xx厅"
, другой"xx房间xx卫"
, но большинство из них - это данные из xx room xx hall. И для чего-то вроде"11房间3卫"
или"5房间0卫"
Эти планировки явно не являются жилыми секонд-хэндами (не входят в сферу нашего рассмотрения), поэтому мы окончательно решили удалить все данные в формате «хх комната хх ванная», и оставить только"xx室xx厅"
Данные.
Функция макета обрабатывается следующим образом:
Вторая строка означает, что зарезервированы только данные «xx room xx hall», но данные в этом формате нельзя использовать в качестве входных данных модели. Новые функции (например, строки 5 и 6), это может работать лучше.
Конкретное использование заключается в использованииstr.extract()
метод, содержащий регулярные выражения.
# 只考虑“室”和“厅”,将其它少数“房间”和“卫”移除
df = df.loc[df['Layout'].str.extract('^\d(.*?)\d.*?') == '室']
# 提取“室”和“厅”创建新特征
df['Layout_room_num'] = df['Layout'].str.extract('(^\d).*', expand=False).astype('int64')
df['Layout_hall_num'] = df['Layout'].str.extract('^\d.*?(\d).*', expand=False).astype('int64')
Year
у нас есть другойYear
Характеристикой является период времени, когда дом был построен. Существует много типов лет, распределенных между 1950 и 2018 годами. Если каждое отдельное значение года используется в качестве собственного значения, мы не можем выяснить, какое влияние оказывает год на цену, потому что годы разделены слишком точно. Следовательно, нам нужно только преобразовать непрерывный числовой признак ГодДискретизация и биннинг.
Как делить бины зависит от реальных потребностей бизнеса, блогер не стал делить бины вручную для удобства, а использовал qcut панд для деления по медиане, и количество делений составило 8 равных частей.
# 按中位数对“Year”特征进行分箱
df['Year'] = pd.qcut(df['Year'],8).astype('object')
Вот результат binning Year :
Direction
Эта функция была более запутанной, пока с ней не разобрались.Я думал, что это проблема поискового робота, но я лично отправился в Ляньцзя, чтобы увидеть ее, и ориентация действительно была такой.
Как видно выше, как"西南西北北"
или"东东南南"
Такая ориентация не соответствует здравому смыслу (во всяком случае, я не могу этого понять). Поэтому нам нужно обрабатывать эти беспорядочные данные.Специфический способ реализации заключается в том, что блогер сам написал функцию.direct_func
, основная идея состоит в том, чтобы комбинировать различные повторяющиеся, но разные собственные значения, такие как"西南北"
и"南西北"
и удалите некоторые необоснованные значения, такие как"西南西北北"
Ждать.
затем пройтиapply()
Метод преобразует формат данных Direction, код выглядит следующим образом:
# 对“Direction”特征
d_list_one = ['东','西','南','北']
d_list_two = ['东西','东南','东北','西南','西北','南北']
d_list_three = ['东西南','东西北','东南北','西南北']
d_list_four = ['东西南北']
df['Direction'] = df['Direction'].apply(direct_func)
df = df.loc[(df['Direction']!='no')&(df['Direction']!='nan')]
Результат после обработки следующий, все ориентации с одинаковым содержанием, но разным порядком объединяются, а также удаляются аномальные ориентации.
Создать новую функцию
Иногда недостаточно полагаться на какие-то существующие функции, необходимо определить какие-то новые функции, исходя из понимания бизнеса, а затем попробовать влияние этих новых функций на модель.Этот метод часто используется в реальных боевых действиях.
Здесь мы пытаемся добавить количество «комнат» и «залов» в качестве общего числового признака, а затем использовать отношение размера дома к общему количеству в качестве нового признака, который можно понимать как"每个房间的平均面积大小"
. Конечно, новые функции не являются фиксированными и могут быть гибко определены в соответствии с их собственным пониманием.
# 根据已有特征创建新特征
df['Layout_total_num'] = df['Layout_room_num'] + df['Layout_hall_num']
df['Size_room_ratio'] = df['Size']/df['Layout_total_num']
# 删除无用特征
df = df.drop(['Layout','PerPrice','Garden'],axis=1)
Окончательно удалите старые функции Layout, PerPrice, Garden.
One-hot coding
Эта частьOne-hot 独热编码
, потому что такие функции, как «Регион», «Год» (после дискретного бинирования), «Направление», «Ремонт», «Лифт» и т. д. — все это нечисловые типы фиксированных категорий, и в качестве входных данных модели нам необходимо количественно определить эти нечисловые значения.
При отсутствии определенного порядка (типа упорядочения) очень распространенной практикой является использование one-hot encoding для обработки категориальных данных, в пандах это очень просто, то есть использоватьget_dummies()
метод и не используйте однократное нагревание для данных с фиксированным соотношением, таких как Размер, Блогер использует функцию, инкапсулированную им самим, для реализации автоматического количественного определения данных фиксированного типа.
закласс, порядок, расстояние, соотношениеСчитается, что эти четыре очень важных типа данных хорошо знакомы партнерам, присоединившимся к Планете знаний.Студенты, которые хотят узнать больше, могут отсканировать последний QR-код для проверки.
# 对于object特征进行onehot编码
df,df_cat = one_hot_encoder(df)
Вышеупомянутая разработка функции завершена.
корреляция признаков
использовать нижеseaborn
изheatmap
метод визуализации корреляции признаков.
# data_corr
colormap = plt.cm.RdBu
plt.figure(figsize=(20,20))
# plt.title('Pearson Correlation of Features', y=1.05, size=15)
sns.heatmap(df.corr(),linewidths=0.1,vmax=1.0, square=True, cmap=colormap, linecolor='white', annot=True)
Если цвет красноватый или голубоватый, это означает, что коэффициент корреляции велик, то есть два признака имеют одинаковую степень влияния на целевую переменную, то есть имеется серьезная повторяющаяся информация, которая вызовет переоснащение. Следовательно, с помощью корреляционного анализа признаков мы можем выяснить, какие признаки имеют серьезное перекрытие информации, а затем выбрать лучший.
прогноз моделирования данных
Чтобы облегчить понимание, блогер сделал некоторые упрощения в моделировании.Метод стратегии модели выглядит следующим образом:
- использовать
Cart决策树
Регрессионная модель анализа и прогнозирования цен на вторичное жилье - использовать
交叉验证
Метод полностью использует набор данных для обучения, чтобы избежать влияния неравномерного разделения данных. - использовать
GridSearchCV
метод оптимизации параметров модели - использовать
R2评分
метод оценки прогнозов модели
Описанный выше метод моделирования относительно прост и призван помочь каждому понять процесс моделирования и анализа. С постепенным углубленным пониманием блоггеры будут вводить более практичный контент.
раздел данных
# 转换训练测试集格式为数组
features = np.array(features)
prices = np.array(prices)
# 导入sklearn进行训练测试集划分
from sklearn.model_selection import train_test_split
features_train, features_test, prices_train, prices_test = train_test_split(features, prices, test_size=0.2, random_state=0)
Приведенные выше данные разделены на обучающий набор и тестовый набор, обучающий набор используется для построения модели, а тестовый набор используется для проверки точности прогнозирования модели. использоватьsklearn的 model_selection
Для достижения вышеуказанной функции деления.
Моделирование
from sklearn.model_selection import KFold
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import make_scorer
from sklearn.model_selection import GridSearchCV
# 利用GridSearchCV计算最优解
def fit_model(X, y):
""" 基于输入数据 [X,y],利于网格搜索找到最优的决策树模型"""
cross_validator = KFold(10, shuffle=True)
regressor = DecisionTreeRegressor()
params = {'max_depth':[1,2,3,4,5,6,7,8,9,10]}
scoring_fnc = make_scorer(performance_metric)
grid = GridSearchCV(estimator = regressor, param_grid = params, scoring = scoring_fnc, cv = cross_validator)
# 基于输入数据 [X,y],进行网格搜索
grid = grid.fit(X, y)
# print pd.DataFrame(grid.cv_results_)
return grid.best_estimator_
# 计算R2分数
def performance_metric(y_true, y_predict):
"""计算并返回预测值相比于预测值的分数"""
from sklearn.metrics import r2_score
score = r2_score(y_true, y_predict)
return score
использовалKFold
метод замедления переобучения,GridSearchCV
метод автоматического поиска оптимальных параметров и, наконец, использованиеR2
Оценка, чтобы оценить модель.
Модель оптимизации настройки параметров
import visuals as vs
# 分析模型
vs.ModelLearning(features_train, prices_train)
vs.ModelComplexity(features_train, prices_train)
optimal_reg1 = fit_model(features_train, prices_train)
# 输出最优模型的 'max_depth' 参数
print("最理想模型的参数 'max_depth' 是 {} 。".format(optimal_reg1.get_params()['max_depth']))
predicted_value = optimal_reg1.predict(features_test)
r2 = performance_metric(prices_test, predicted_value)
print("最优模型在测试数据上 R^2 分数 {:,.2f}。".format(r2))
Поскольку дерево решений склонно к переоснащению, мы используем метод наблюдения за кривой обучения, чтобы проверить глубину дерева решений и определить, является ли модель переоснащением. Ниже приведен график наблюдаемой кривой обучения:
По наблюдениям параметры наиболее идеальной модели"max_depth"
равно 10. В этом случае достигается оптимальный баланс смещения и дисперсии Наконец, оценка R2 модели на тестовых данных, то есть точность прогнозирования цен на вторичное жилье, составляет:0.81
.
Суммировать
Вышеупомянутый полный проект от анализа данных до майнинга завершен, Он относительно прост для проекта, и цель состоит в том, чтобы каждый понял весь процесс анализа. Есть много областей, которые можно улучшить и которые можно заменить лучшими и более надежными решениями.Некоторые улучшения рассматриваются следующим образом:
- Получите более ценную информацию о функциях, такую как школьные округа, близлежащие станции метро, торговые центры и т. д.
- Улучшите разработку функций, например, эффективный выбор функций
- Моделируйте с лучшими алгоритмами модели или используйте слияние моделей
Блогер с полным кодом проекта поделился им в知识星球
, последующие блоггеры продолжат делиться более практичным контентом,Kaggle竞赛项目
,а также互联网金融风险控制项目
, чтобы присоединиться к сканированию планеты, отсканируйте следующий QR-код:
Обратите внимание на публичный аккаунт WeChat:PythonНаука о данныхчтобы увидеть больше отличного контента.