用神经网络实现-Facebook营销组合分类预测
Facebook营销组合分类预测
背景信息
在Facebook注册用户超过20亿人,每天会产生超过百亿条的消息、近10亿张新图片,借助大数据技术,Facebook可以跟踪用户网络行为、进行面部识别和标注、分析用户喜好等等,从而向广告客户的市场营销人员展示受众对于品牌、事件、活动和主题的反应。Facebook实际上已经成为一家大数据驱动的广告公司。为了展示其收集和挖掘大数据的能力,Facebook找伦敦创意机构Human After All设计了一副【市场洞察扑克牌】,每张牌都图文并茂地提供了一条关于用户的数据洞察信息,例如:
- 41%的英国人在11月就开始圣诞节采购
- 已婚人士比单身更喜欢讨论食物(31% vs 24%)
- 63%谈论奢侈品话题的用户年龄在18-34岁之间
- 61%的英国Facebook用户提前一周就开始为情人节做准备
- 刚刚有宝宝的父母们花在手机上的时间是没有宝宝的用户的 1.6 倍
- 母亲节那天,关于母亲节的讨论多达 9430 万次
任务说明
假设你是Facebook的大数据科学家,你的职责是为某个目标客户群,提供一组【市场洞察扑克牌】组合,为其提供市场营销策略指导,在帮助客户成功的同时也为Facebook获得广告收入。
基础规则是:你只能给客户5张牌。客户基于这5条不同的市场洞察信息制定市场营销策略,因此5张牌的不同组合方案,会产生截然不同的经济效果,也为Facebook带来不一样的收入。
52张牌对应52条市场洞察信息,会产生过百万的组合方式,你需要通过大数据技术,找出不同组合方案所对应的效果,并分出“市场洞察信息组合优化等级”,Facebook广告销售人员就可以根据这个优化等级表开展销售工作。
经Facebook允许,你做了一次小规模内测,通过内测你收到了25000条的反馈数据,根据客户反馈回来的收益,你对每条数据进行了0~9的组合优化等级标注。 接下去,你需要设计算法,根据上述 25000条内测数据及其优化等级标注,找出内在规律,为剩余100万条随机组合方案进行优化等级标注。
数据集描述
训练数据集包括11个字段,字段的含义如下所示,牌面花色用C,D,H,S表示,分表代表梅花、方块、红桃和黑桃,牌面大小用1-10以及J、Q、K来表示。需要注意,字段11是每条数据的优化等级标注。
程序实现
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
import tensorflow as tf
def load_data(path):
"""数据加载方法。
根据指定文件的路径进行数据加载。同时,进行数据清洗以及必要的转换。
将非数值类型转换成数值类型(使用One-Hot编码)。
Parameters
------
path : str
文件的路径。
Returns
------
(X, y) : tuple
返回加载并且转换之后的数据(元祖类型)。
X : 样本的特征。
y : 样本的标签。
"""
data = pd.read_csv(path, header=None)
# 删除重复值。
data.drop_duplicates(inplace=True)
# 将数据集分为特征与标签。
X, y = data.iloc[:, :-1], data.iloc[:, -1]
# le = LabelEncoder()
# X = X.apply(lambda item: le.fit_transform(item))
ohe = OneHotEncoder()
# OneHotEncoder编码默认返回的是稀疏矩阵的类型(matrix),
# 我们可以调用toarray将其转换为ndarray数组。
X = pd.DataFrame(ohe.fit_transform(X).toarray())
# 目前,列标签是数值类型的,对我们后面应用tensorflow会出现小问题(支持Python中合法的标示符的形式)。
# 我们对列标签进行转换(转换为Python中合法的标示符的形式)。
X.columns = X.columns.map(lambda name: f"c{name}")
return X, y
def train_input_fn(features, labels):
"""用来训练的函数,在分类器中会调用该函数。
Parameters
------
featrues : 类数组类型。形状为(样本数量, 特征数量)
用来训练的样本特征。
labels : 样本数据的标签。形状为(样本数量,)
样本对应的标签。
Returns
------
data : tf.Data.DataSet
用于训练的数据集。
"""
# 创建数据集。
dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
# 对数据集进行洗牌,并且制定重复的次数(epoch),再制定每个批次传递的样本数量。
dataset = dataset.shuffle(10000, seed=0).repeat(10).batch(50)
return dataset
def eval_input_fn(features, labels=None):
"""评估或者预测的函数。
Parameters
-----
featrues : 类数组类型。形状为(样本数量, 特征数量)
用来评估或预测的样本特征。
labels : 样本数据的标签。形状为(样本数量,)
样本对应的标签。如果labels为None,则表示进行预测。
Returns
-----
data : tf.Data.DataSet
用于评估或预测的数据集。
"""
# features要求是字典类型,我们在这里将其转换为字典类型。
features = dict(features)
# 分为评估与预测两种情况。
if labels is None:
inputs = features
else:
inputs = (features, labels)
dataset = tf.data.Dataset.from_tensor_slices(inputs)
# 这里是进行评估或测试,无需再去打乱样本的顺序,与重复样本数量。
dataset = dataset.batch(100)
return dataset
X, y = load_data("data.csv")
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.25, random_state=0)
# 定义一个列表,用来保存分类器需要的特征列。
my_feature_column = []
for key in train_X.keys():
# 使用列表加入特征列。key参数指定特征列的名字。
my_feature_column.append(tf.feature_column.numeric_column(key=key))
# classifier = tf.estimator.DNNClassifier(feature_columns=my_feature_column, n_classes=10,
# hidden_units=[512] * 2, optimizer=tf.train.AdamOptimizer())
classifier = tf.estimator.DNNClassifier(feature_columns=my_feature_column, n_classes=10,
hidden_units=[512] * 2, optimizer=tf.train.AdamOptimizer(), config=config)
# 训练方法。input_fn指定一个函数,该函数需要返回一个数据集DataSet,train方法就是使用函数返回的数据集
# 进行训练的。
classifier.train(input_fn=lambda : train_input_fn(train_X, train_y))
# 评估的方法。
# classifier.evaluate(input_fn=lambda : eval_input_fn(test_X, test_y))
# 进行测试方法。(测试方法没有label。该方法返回一个生成器。
# 我们可以对生成器迭代,获取元素。元素包含样本的测试结果信息。
g = classifier.predict(input_fn=lambda : eval_input_fn(test_X))
from datetime import datetime
# 我们也可以配置检查点的保存位置。
config = tf.estimator.RunConfig(
# 设置检查点的保存目录。
model_dir=f"temp/{datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')}",
# 设置保存件检查点的时间间隔。
save_checkpoints_secs=100 * 3600,
# 设置最多保存检查点的数量。
keep_checkpoint_max=3)
# DNNClassifier 在训练的时候,第一次与最后一次,一定会生成检查点。
# classifier = tf.estimator.DNNClassifier(feature_columns=my_feature_column, n_classes=10,
# hidden_units=[512] * 2, optimizer=tf.train.AdamOptimizer(), config=config)