广东省建设八大员网站,addthis wordpress,网盘做网站,北京官网seo推广拆分学习的概念
拆分学习的核心思想是拆分网络结构。每一个参与方拥有模型结构的一部分#xff0c;所有参与方的模型合在一起形成一个完整的模型。训练过程中#xff0c;不同参与方只对本地模型进行正向或者反向传播计算#xff0c;并将计算结果传递给下一个参与方。多个参…拆分学习的概念
拆分学习的核心思想是拆分网络结构。每一个参与方拥有模型结构的一部分所有参与方的模型合在一起形成一个完整的模型。训练过程中不同参与方只对本地模型进行正向或者反向传播计算并将计算结果传递给下一个参与方。多个参与方通过联合模型进行训练直至最终收敛。
一个典型的拆分学习例子 Alice持有数据和基础模型。Bob只有数据、基础模型和fuse模型。
Alice使用自己的数据和基础模型得到 hidden0然后发送给Bob。Bob使用自己的数据和基础模型得到 hidden1。Agg Layer使用 hidden_0 和 hidden_1 作为输入并输出聚合后的隐层。Bob把聚合后的隐层作为fuse模型的输入计算得到梯度。梯度被拆分成两部分分别返回给Alice和Bob。Alice和Bob使用各自收到的梯度更新基础模型。
SplitRec
SplitRec是隐语拆分学习针对跨域推荐场景中的模型训练所提供的一系列优化算法和策略。
在传统推荐场景中用户的数据通常需要上传到中央服务器进行模型训练。而跨域推荐场景是指联合分布在不同域的数据进行分布式训练的推荐场景。例如一个用户在一个短视频平台看了很多短视频在另一个电商平台被推荐相关的广告电商平台除了自有数据外也希望从短视频平台的数据中挖掘相关的信息。同时出于数据安全考虑各平台数据不能被上传到中央服务器进行集中式的机器学习训练这种联合分布在不同域的数据进行模型训练的场景很适合用联邦学习中的拆分学习。
跨域推荐模型将不同域的用户数据联合起来建模相比传统推荐系统收集到的数据更多更丰富同时由于数据分布在不同域在精度、效率和安全性上都对模型的训练提出了很多挑战主要有以下三点
模型效果上例如DeepFM等复杂模型能否直接放到拆分框架中使用训练效率上模型训练中每个 batch 的前反向计算中的通信是否会严重降低训练效率安全性上通信的中间数据是否会造成信息泄露引起安全性问题
SplitRec 在效果、效率和安全方面对拆分模型训练做了很多优化。
模型效果上SplitRec 提供了拆分 DeepFM、BST、MMoe 等模型的封装。训练效率上SplitRec 借由隐语拆分学习框架的能力提供了压缩、流水并行等策略来提升训练效率。安全性上SplitRec提供了安全聚合、差分隐私等安全策略。同时也提供了一些针对拆分学习的攻击方法来验证不同攻击手段对拆分模型的影响后续也会更新相关防御方法。
实践:在隐语中使用拆分 DeepFM 算法
DeepFM算法结合了FM和神经网络的长处可以同时提升低维和高维特征相比WideDeep模型还免去了特征工程的部分。 整体上来看。这个模型可以分成两个部分分别是FM部分以及Deep部分。这两个部分的输入是一样的并没有像Wide Deep模型那样做区分。Deep的部分用来训练这些特征的高维的关联而FM模型会通过隐藏向量V的形式来计算特征之间的二维交叉的信息。
隐语中的DeepFM
拆分的详细过程可以来看这里
SplitRec在隐语中使用拆分 DeepFM 算法Tensorflow 后端 | SecretFlow v1.9.0b1 | 隐语 SecretFlow
环境设置
import secretflow as sf# Check the version of your SecretFlow
print(The version of SecretFlow: {}.format(sf.__version__))# In case you have a running secretflow runtime already.
sf.shutdown()
sf.init([alice, bob, charlie], addresslocal, log_to_driverFalse)
alice, bob, charlie sf.PYU(alice), sf.PYU(bob), sf.PYU(charlie) 数据集介绍
我们这里将使用最经典的MovieLens数据集来进行演示。 MovieLens是一个开放式的推荐系统数据集包含了电影评分和电影元数据信息。
我们对数据进行了切分
- alice: “UserID”, “Gender”, “Age”, “Occupation”, “Zip-code”
- bob: “MovieID”, “Rating”, “Title”, “Genres”, “Timestamp”
下载并处理数据
数据拆分处理
%%capture
%%!
wget https://secretflow-data.oss-accelerate.aliyuncs.com/datasets/movielens/ml-1m.zip
unzip ./ml-1m.zip
# Read the data in dat format and convert it into a dictionary
def load_data(filename, columns):data {}with open(filename, r, encodingunicode_escape) as f:for line in f:ls line.strip(\n).split(::)data[ls[0]] dict(zip(columns[1:], ls[1:]))return data
fed_csv {alice: alice_ml1m.csv, bob: bob_ml1m.csv}
csv_writer_container {alice: open(fed_csv[alice], w), bob: open(fed_csv[bob], w)}
part_columns {alice: [UserID, Gender, Age, Occupation, Zip-code],bob: [MovieID, Rating, Title, Genres, Timestamp],
}
for device, writer in csv_writer_container.items():writer.write(ID, ,.join(part_columns[device]) \n)
f open(ml-1m/ratings.dat, r, encodingunicode_escape)users_data load_data(./ml-1m/users.dat,columns[UserID, Gender, Age, Occupation, Zip-code],
)
movies_data load_data(./ml-1m/movies.dat, columns[MovieID, Title, Genres])
ratings_columns [UserID, MovieID, Rating, Timestamp]rating_data load_data(./ml-1m/ratings.dat, columnsratings_columns)def _parse_example(feature, columns, index):if Title in feature.keys():feature[Title] feature[Title].replace(,, _)if Genres in feature.keys():feature[Genres] feature[Genres].replace(|, )values []values.append(str(index))for c in columns:values.append(feature[c])return ,.join(values)index 0
num_sample 1000
for line in f:ls line.strip().split(::)rating dict(zip(ratings_columns, ls))rating.update(users_data.get(ls[0]))rating.update(movies_data.get(ls[1]))for device, columns in part_columns.items():parse_f _parse_example(rating, columns, index)csv_writer_container[device].write(parse_f \n)index 1if num_sample 0 and index num_sample:break
for w in csv_writer_container.values():w.close()
到此就完成了数据的处理和拆分
得到
alice: alice_ml1m.csv
bob: bob_ml1m.csv
! head alice_ml1m.csv
! head bob_ml1m.csv
构造data_builder_dict
# alice
def create_dataset_builder_alice(batch_size128,repeat_count5,
):def dataset_builder(x):import pandas as pdimport tensorflow as tfx [dict(t) if isinstance(t, pd.DataFrame) else t for t in x]x x[0] if len(x) 1 else tuple(x)data_set (tf.data.Dataset.from_tensor_slices(x).batch(batch_size).repeat(repeat_count))return data_setreturn dataset_builder# bob
def create_dataset_builder_bob(batch_size128,repeat_count5,
):def _parse_bob(row_sample, label):import tensorflow as tfy_t label[Rating]y tf.expand_dims(tf.where(y_t 3,tf.ones_like(y_t, dtypetf.float32),tf.zeros_like(y_t, dtypetf.float32),),axis1,)return row_sample, ydef dataset_builder(x):import pandas as pdimport tensorflow as tfx [dict(t) if isinstance(t, pd.DataFrame) else t for t in x]x x[0] if len(x) 1 else tuple(x)data_set (tf.data.Dataset.from_tensor_slices(x).batch(batch_size).repeat(repeat_count))data_set data_set.map(_parse_bob)return data_setreturn dataset_builderdata_builder_dict {alice: create_dataset_builder_alice(batch_size128,repeat_count5,),bob: create_dataset_builder_bob(batch_size128,repeat_count5,),
}
from secretflow.ml.nn.applications.sl_deep_fm import DeepFMbase, DeepFMfuse
from secretflow.ml.nn import SLModelNUM_USERS 6040
NUM_MOVIES 3952
GENDER_VOCAB [F, M]
AGE_VOCAB [1, 18, 25, 35, 45, 50, 56]
OCCUPATION_VOCAB [i for i in range(21)]
GENRES_VOCAB [Action,Adventure,Animation,Childrens,Comedy,Crime,Documentary,Drama,Fantasy,Film-Noir,Horror,Musical,Mystery,Romance,Sci-Fi,Thriller,War,Western,
]
DeepFMBase有4个参数
-dnn_units_size: 这个参数需要提供一个list来对dnn部分进行定义比如[256,32]意思是中间两个隐层分别是256和32
-dnn_activation: dnn 的激活函数eg:relu
-preprocess_layer: 需要对输入进行处理传入一个定义好的keras.preprocesslayer
-fm_embedding_dim: fm vector的维度是多少
# Define alices basenet
def create_base_model_alice():# Create modeldef create_model():import tensorflow as tfdef preprocess():inputs {UserID: tf.keras.Input(shape(1,), dtypetf.string),Gender: tf.keras.Input(shape(1,), dtypetf.string),Age: tf.keras.Input(shape(1,), dtypetf.int64),Occupation: tf.keras.Input(shape(1,), dtypetf.int64),}user_id_output tf.keras.layers.Hashing(num_binsNUM_USERS, output_modeone_hot)user_gender_output tf.keras.layers.StringLookup(vocabularyGENDER_VOCAB, output_modeone_hot)user_age_out tf.keras.layers.IntegerLookup(vocabularyAGE_VOCAB, output_modeone_hot)user_occupation_out tf.keras.layers.IntegerLookup(vocabularyOCCUPATION_VOCAB, output_modeone_hot)outputs {UserID: user_id_output(inputs[UserID]),Gender: user_gender_output(inputs[Gender]),Age: user_age_out(inputs[Age]),Occupation: user_occupation_out(inputs[Occupation]),}return tf.keras.Model(inputsinputs, outputsoutputs)preprocess_layer preprocess()model DeepFMbase(dnn_units_size[256, 32],preprocess_layerpreprocess_layer,)model.compile(losstf.keras.losses.binary_crossentropy,optimizertf.keras.optimizers.Adam(),metrics[tf.keras.metrics.AUC(),tf.keras.metrics.Precision(),tf.keras.metrics.Recall(),],)return model # need wrapreturn create_model
# Define bobs basenet
def create_base_model_bob():# Create modeldef create_model():import tensorflow as tf# define preprocess layerdef preprocess():inputs {MovieID: tf.keras.Input(shape(1,), dtypetf.string),Genres: tf.keras.Input(shape(1,), dtypetf.string),}movie_id_out tf.keras.layers.Hashing(num_binsNUM_MOVIES, output_modeone_hot)movie_genres_out tf.keras.layers.TextVectorization(output_modemulti_hot, splitwhitespace, vocabularyGENRES_VOCAB)outputs {MovieID: movie_id_out(inputs[MovieID]),Genres: movie_genres_out(inputs[Genres]),}return tf.keras.Model(inputsinputs, outputsoutputs)preprocess_layer preprocess()model DeepFMbase(dnn_units_size[256, 32],preprocess_layerpreprocess_layer,)model.compile(losstf.keras.losses.binary_crossentropy,optimizertf.keras.optimizers.Adam(),metrics[tf.keras.metrics.AUC(),tf.keras.metrics.Precision(),tf.keras.metrics.Recall(),],)return model # need wrapreturn create_model
定义Fusenet
def create_fuse_model():# Create modeldef create_model():import tensorflow as tfmodel DeepFMfuse(dnn_units_size[256, 256, 32])model.compile(losstf.keras.losses.binary_crossentropy,optimizertf.keras.optimizers.Adam(),metrics[tf.keras.metrics.AUC(),tf.keras.metrics.Precision(),tf.keras.metrics.Recall(),],)return modelreturn create_model
base_model_dict {alice: create_base_model_alice(), bob: create_base_model_bob()}
model_fuse create_fuse_model()
from secretflow.data.vertical import read_csv as v_read_csvvdf v_read_csv({alice: alice_ml1m.csv, bob: bob_ml1m.csv}, keysID, drop_keysID
)
label vdf[Rating]data vdf.drop(columns[Rating, Timestamp, Title, Zip-code])
data[UserID] data[UserID].astype(string)
data[MovieID] data[MovieID].astype(string)sl_model SLModel(base_model_dictbase_model_dict,device_ybob,model_fusemodel_fuse,
)
history sl_model.fit(data,label,epochs5,batch_size128,random_seed1234,dataset_builderdata_builder_dict,
)
到这里我们已经使用隐语提供的deepfm封装完成了movieLens数据集上的推荐任务训练。
总结
我们通过movieLens数据集上的推荐任务来演示了如何通过隐语来实现DeepFM。
1.下载并拆分数据集
2.定义好数据处理的dataloader
3.定义好数据预处理的preprocesslayer,定义好dnn结构调用DeepFMBaseDeepFMFuse来进行模型定义
4.使用SLModel进行训练预测评估即可。