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 numpy as np import pandas as pd from sklearn.preprocessing import LabelEncoder from sklearn.preprocessing import OneHotEncoder import tensorflow as tf from sklearn.model_selection import train_test_split
def load_data(path): """数据加载方法。 根据指定文件的路劲进行数据的加载。 进行数据清洗及必要的转换 将非数值类型转换成数值类型(one-hot编码) Parameters ------- """ data = pd.read_csv(path,header=None) # data.head() # data.info() # 查看重复值有几个 # np.sum(data.duplicated()) # data[data.duplicated()] data.drop_duplicates(inplace=True) # data[data.duplicated()] # display(data.head(10)) # 将数据集分为特征与标签 X, y = data.iloc[:,:-1],data.iloc[:,-1] display(X.head(10)) # 进行标签编码 le = LabelEncoder() # 针对每一个操作 # 进行排序之后再编码 保证每一个字符在不同的列编码一致 # 原本的数据没有大小之分 使用标签编码之后有大小之分 权重影响不一致 X = X.apply(lambda item: le.fit_transform(item)) # display(X.head(10)) # 当数据没有大小之分 映射到多维空间 one-hot 编码 彼此距离相等 # 默认返回的是稀疏矩阵的类型 可以调用toarray转换为ndarray数组 onh = OneHotEncoder() # display(onh.fit_transform(X).toarray()) # X = pd.DataFrame(onh.fit_transform(X).toarray()) # display(X.head()) # 目前列标签是数值类型的 对我们后面的应用TensorFlow会出现问题 支持python中合法的标识符 # 的形式 我们对列表签进行转换 转换成合法的标识符的形式 X.columns = X.columns.map(lambda name: f"c{name}") # display(X.head()) return X, y X ,y = load_data('data.csv') y.value_counts()
X ,y = load_data('data.csv') # 查看具体数据 发现数据不均衡 y.value_counts() # 用深度神经网络来解决 DNN
def train_input_fn(features, labels): """用来训练的函数 在分类器中会调用该函数 Parameters ----- features : 类数组对象 形状(样本数量,样本标签) 用来训练的样本特征 labels : 样本数据的标签 形状(样本数量) 样本对应的标签 Returns ---- data : tf.Data.DataSet 用于训练的数据集 """ # 创建数据集 dataset = tf.data.Dataset.from_tensor_slices( (dict(features), labels)) # 对数据集进行洗牌 并且指定重复的次数 再指定每个批次传递的样本数量 dataset = dataset.shuffle(10000, seed=0).repeat(10).batch(50) return dataset # 评估预测函数 def eval_input_fn(features, labels= None): """评估或者预测的函数 评估有label 预测没有 """ # 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(): # 使用列表加入特征列 # optimizer 优化器 hidden_units隐藏层 my_feature_column.append(tf.feature_column.numeric_column(key=key)) # classfier = tf.estimator.DNNClassifier(feature_columns=my_feature_column,n_classes=10, # hidden_units=[512,512], optimizer='SGD') classfier = tf.estimator.DNNClassifier(feature_columns=my_feature_column,n_classes=10, hidden_units=[512,512], optimizer=tf.train.AdadeltaOptimizer()) classfier.train(input_fn=lambda : train_input_fn(train_X, train_y)) classfier.evaluate(input_fn=lambda : eval_input_fn(test_X,test_y)) # classfier.predict(input_fn=lambda : eval_input_fn(test_X))