这篇文章不涉及原理,直接上代码运行。结合之前的文章《数据挖掘建模流程和所需工具汇总》效果更佳ノ~YO(^U^)
建模主要工作就是调包调参,你懂的(●’◡’●)
from __future__ import print_function #把下一个新版本的特性导入到当前版本
import statsmodels.api as sm #statsmodels统计建模和计量经济学工具包,包括一些描述统计、统计模型估计和推断
import pandas as pd, numpy as np #pandas:分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算)
pd.set_option('display.max_columns',None) #显示所有列
pd.set_option('display.max_rows',None) #显示所有行
#from ipython.core.interactiveshell import InteractiveShell #Ipython一般情况下这只能显示最后一行的变量,可以通过修改内核选项ast_node_interactivity,使得独占一行的所有变量或者语句都自动显示。
#InteractiveShell.ast_node_interactivity ='all'
import matplotlib.pyplot as plt #2D绘图库
import seaborn as sns #基于Matplotlib的Python数据可视化库
from sklearn.model_selection import train_test_split #scikit-learnscikit-learn(简记sklearn),是机器学习算法库。这个模块主要是对数据的分割,以及与数据划分相关的功能
from sklearn.preprocessing import LabelEncoder,StandardScaler,MinMaxScaler # 预处理数预处理数据的方法
from sklearn.tree import tree,export_graphviz,DecisionTreeClassifier #树模型
from sklearn.linear_model import LogisticRegression #线性模型
from sklearn.ensemble import RandomForestClassifier,GradientBoostingClassifier,BaggingClassifier,VotingClassifier #集成模型,随机森林RF,梯度提升GBDT、装袋、投票
#imbalanced-learn;bagging装袋
from mlxtend.classifier import StackingClassifier #machine learning extensions,高级的机器学习扩展库,算是sklearn的一个补充和辅助;stacking堆积
from sklearn.model_selection import ShuffleSplit,cross_validate,ShuffleSplit,GridSearchCV,KFold,cross_val_score #随机分配,交叉验证,随机划分训练集、测试集,网格搜索, K折交叉验证,交叉验证指标
from imblearn.under_sampling import RandomUnderSampler #下采样/欠采样
from imblearn.over_sampling import RandomOverSampler,SMOTE #上采样/过采样
import xgboost as xgb
from xgboost import XGBClassifier
import lightgbm as lgb
from lightgbm import LGBMClassifier
import catboost as cb
from catboost import CatBoostClassifier
from sklearn.metrics import confusion_matrix,precision_score,accuracy_score,mean_squared_error,classification_report #各种评价模型效果的指标
import time
import datetime
import woe.feature_process as fp #常用于评分卡模型
import woe.eval as eval
from sklearn.feature_selection import SelectKBest,f_regression,RFE,chi2,SelectFromModel #特征选择:回归问题(y连续);递归特征消除 (Recursive Feature Elimination),卡方检验,基于模型
from sklearn import datasets
import warnings #通常用于提示用户一些错误或者过时的用法
warnings.filterwarnings("ignore") #关闭warnings
data = pd.read_csv('file.csv',index_col=False,dytpe={'colname1':object,'colname2':object}) #前面带0的数据记得要转化成object,不然导入后0就消失了
目前比较主流,很多公司已经配置spark连接hive的参数,可以直接读取hive数据.
from pyspark.conf import SparkConf
from pyspark.sql import SparkSession
conf = SparkConf().setExecutorEnv('PYTHONHASHSEED','123') #使用python3,需加上
# 创建SparkSession 对象
spark = SparkSession.builder.config(conf=conf).appName("PySpark SQL example").master("local").enableHiveSuppert().getOrCreate()
sc = spark.sparkContext #SQLContext它是在Apache Spark中处理结构化数据(行和列)的入口点,它允许创建DataFrame对象以及执行SQL查询。
sql_d = "SELECT * FROM XXX WHERE XXX" #sql语句
data = spark.sql(sql_d) #读出的是spark格式
data_df = data.toPandas() #转换成pandas的DataFrame格式
## toPanda会消耗大量内存,内存不够,报错。怎么处理?
### 2.2.1 修改SparkConfig
spark_config = [["spark.driver.maxResultSize","50g"]]
conf.setAll(spark_config)
### 2.2.2 分片拉取数据
tailSplice = list(range(0,10))
for i in tailSplice:
sql_d = "SELECT * FROM XXX WHERE XXX and substr(seqence,-1,1)={i}".format(i=i)
data = spark.sql(sql_d)
sc.stop() #暂停,开启会一直消耗内存
一般自己学习时可直接通过已有数据进行实践。本文也是通过此数据进行实践的。
# 导入癌症数据
cancer=datasets.load_breast_cancer()
data=cancer.data
target=cancer.target
#转化成DataFrame格式
df_data = pd.DataFrame(data,columns=cancer.feature_names)
df_target = pd.DataFrame(target,columns=['target'])
df = df_data
df['target'] = df_target
#df = pd.concat([df_data,df_target])
'''
print(cancer.feature_names) # ['mean radius' 'mean texture' 'mean perimeter' 'mean area'
'mean smoothness' 'mean compactness' 'mean concavity'
'mean concave points' 'mean symmetry' 'mean fractal dimension'
'radius error' 'texture error' 'perimeter error' 'area error'
'smoothness error' 'compactness error' 'concavity error'
'concave points error' 'symmetry error' 'fractal dimension error'
'worst radius' 'worst texture' 'worst perimeter' 'worst area'
'worst smoothness' 'worst compactness' 'worst concavity'
'worst concave points' 'worst symmetry' 'worst fractal dimension']
print(cancer.target_names) # ['malignant' 'benign']
'''
不同模型对数据要求不一样,有的需要标准化处理,有的不可以有缺失值、文本数据等等。要根据实际情况进行处理。
以下是现在常用的一些预处理,可供借鉴。本文数据很标准,不需要处理。
### 先查看是否存在空值
df.info(verbose=True, null_counts=True) #查看每一列的空值数
pd.isna(df).sum() #同上,使用其一即可
### 3.1.1、空值填充。一般都是根据经验,以及对数据的了解。通常日期用特小或特大日期填充,文本可随意,数值型,也一般用不相关的999、0之类的填充。
data.fillna(value='19700101',True)
### 3.1.2、空值删除。对于空值过多的,直接删除
drop_list = ['colname1','colname2','colname3']
data.drop(drop_list,axis=1,inplace=True)
对于文本型数据,要转化数值型数据
### 标签编码
le = LabelEncoder()
var = ['colname1','colname2','colname3']
for i in var:
data[i] = le.fit_transform(data[i])
###另外一种常用的是独热编码
### 独热编码
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
var = ['colname1','colname2','colname3']
for i in var:
data[i] = ohe.fit_transform(data[i])
### 数据转化
### 日期转化为天数,一般天数比较有计量意义。
now_date = time.strftime("%Y-%m-%d",time.localtime(time.time())) #获取当前日期
data_new = pd.to_datetime(now_date)
data['date'] = ((data_new - pd.to_datetime(data['date'],format='%Y-%m-%d'))/np.timedelta64(1,'D')).astype(np.int)
### 数据标准化
'''
如何判断是否需要标准化:
需要: 基于参数的模型或基于距离的模型,都是要进行特征的归一化,例如逻辑回归等。
不需要:基于树的方法是不需要进行特征的归一化,例如随机森林等。
'''
data_scaled = StandardScaler().fit_transform(data) #标准化
data_scaled = MinMaxScaler().fit_transform(data) #缩放到一个指定的最大和最小值(通常是1-0)之间
## 自变量、因变量划分
'''像之前直接导入的datasets数据,已划分好,可不用此步 '''
data_x = df.drop(['target'],axis=1).values #切分自变量
data_y = df.target.values #切分因变量
## 训练集、测试集划分
train_x, test_x, train_y, test_y = train_test_split(df_data,df_target)
#先查看数据是否不均衡
df["target"].value_counts() #按照target分类计数
## 直接使用imblearn包中的方法(1:1)
rus = RandomUnderSampler(random_state=0) #随机选取数据的子集
X,y=rus.fit_sample(train_x,train_y)
#### 自定义下采样方法(可自定义正负样本比例)
## 方法一
def down_sample(train):
df1 = train[train["target"]==0] #良性
df2 = train[train["target"]==1] #恶性
df3 = df2.sample(frac=0.5) #按0.5比例抽取
return pd.concat([df1,df2])
## 方法二
def under_samp(data,n):
under_samping_seed = 2020
num_malignant = data[data['target']==1].shape[0] #恶性样本数量
benign_users = data[data['target']==0].index.values #良性样本索引
benign_users_selection = np.random.RandomState(under_samping_seed).choice(benign_users,size=round(num_malignant*n),replace=False) #随机选择num_malignant*n个样本
malignant_users = data[data['target']==1].index.values #恶性样本索引
selected_users = list(set(benign_users_selection).union(set(malignant_users)))
new_train = data.loc[selected_users].copy()
retuen new_train
现在数据量普遍比较大,上采样用的较少(至少我很少用)
#随机过采样
ros = RandomOverSampler(random_state=0)
X_resampled, y_resampled = ros.fit_sample(train_x, train_y)
print(Counter(y_resampled))
### 卡方(Chi2)检验
def SelectKFeatures(funcname,k,X,y): #可选关联系数、卡方校验、最大信息系数作为得分计算的方法
X_new = SelectKBest(funcname,k=k).fit_transform(X,y)
a = X_new[0,:]
b = a.tolist()
names = X.columns
c = names.tolist()
features = DataFrame(sorted(zip(b,c,names),reverse=True))
return features
chi2_K_ftrs = SelectKFeatures(chi2,2,df_data,df_target)
#SelectKBest(chi2, k=2).fit_transform(cancer.data, cancer.target)
### 递归特征消除 (Recursive Feature Elimination)
def SelectRFEFeatures(estimator,k,X,y):
X_new = RFE(estimator=estimator, n_features_to_select=k).fit_transform(X,y)
a = X_new[0,:]
b = a.tolist()
names = X.columns
c = names.tolist()
features = DataFrame(sorted(zip(b,c,names),reverse=True))
return features
RFE_K_ftrs = SelectRFEFeatures(estimator=LogisticRegression(),2,df_data,df_target)
#RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(df_data,df_target)
### 4.3.1、基于L1的特征选择 (L1-based feature selection)
def SelectModelFeatures(estimator,k,X,y):
X_new = SelectFromModel(estimator=LogisticRegression(penalty="11",C=0.1)).fit_transform(X,y)
a = X_new[0,:]
b = a.tolist()
names = X.columns
c = names.tolist()
features = DataFrame(sorted(zip(b,c,names),reverse=True))
return features
LR_K_ftrs = SelectModelFeatures(k=2,df_data,df_target)
### 4.3.2、基于树的特征选择 (Tree-based feature selection)
from sklearn.ensemble import ExtraTreesClassifier
def SelectModelFeatures2(estimator,k,X,y):
estimator = ExtraTreesClassifier()
estimator.fit(X, y)
X_new = SelectFromModel(estimator,prefit=True)
a = X_new[0,:]
b = a.tolist()
names = X.columns
c = names.tolist()
features = DataFrame(sorted(zip(b,c,names),reverse=True))
return features
Tree_K_ftrs = SelectModelFeatures2(k=2,df_data,df_target)
### 4.3.3、将特征选择过程融入pipeline (Feature selection as part of a pipeline)
from sklearn.svm import LinearSVC
clf = Pipeline([
('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))),
('classification', RandomForestClassifier())
])
clf.fit(X, y)
tree_model = DecisionTreeClassifier()
RF_model = RandomForestClassifier()
xgb_model = XGBClassifier()
LR_model = LogisticRegression()
GBM_model = GradientBoostingClassifier()
lgb_model = LGBMClassifier()
cat_model = CatBoostClassifier() #2017年俄罗斯Yandex发布的开源机器学习库,是Gradient Boosting(梯度提升)+Categorical Features(类别性特征),也是基于梯度提升决策树的机器学习框架
estimator_list = [tree_model,RF_model,xgb_model,GBM_model,lgb_model]
cv_split = ShuffleSplit(n_splits=6,train_size=0.7,test_size=0.3,random_state=168)
df_columns=['Name','Parameters','Test Accuracy Mean','Test Accuracy Std','Test Recall Mean','Test Precision Mean','Fit Time']
df = pd.DataFrame(columns=df_columns)
row_index=0
scoring = ['accuracy','precision','recall'] #设置评分项
for estimator in estimator_list:
df.loc[row_index,'Name'] = estimator.__class__.__name__
df.loc[row_index,'Parameters'] = str(estimator.get_params())
cv_results = cross_validate(estimator,X,y,scoring=scoring,cv=cv_split) #交叉验证(循环评估)
df.loc[row_index,'Test Accuracy Mean'] = cv_results['test_accuracy'].mean()
df.loc[row_index,'Test Accuracy Std'] = cv_results['test_accuracy'].std()
df.loc[row_index,'Test Recall Mean'] = cv_results['test_recall'].mean()
df.loc[row_index,'Test Precision Mean'] = cv_results['test_precision'].mean()
df.loc[row_index,'Fit Time'] = cv_results['fit_time'].mean()
print(row_index,estimator.__class__.__name__)
print(cv_results['test_accuracy'])
df = df.sort_values(by='Test Accuracy Mean',ascending=False)
print(df)
其实,对于基于决策树的模型,调参的方法都是大同小异。一般都需要如下步骤:
1、首先选择较高的学习率,大概0.1附近,这样是为了加快收敛的速度。这对于调参是很有必要的。
2、对决策树基本参数调参。
3、正则化参数调参。
4、最后降低学习率,这里是为了最后提高准确率。
参数调整一般有两种方法:
1、网格搜索(grid search):速度慢但适用于需要随整个参数进行搜索的情况;随机搜索(random search):速度快但易遗漏一些重要信息。
2、贝叶斯优化(Bayesian optimization),通过Hyperopt模块实现
LightGBM是个快速的、分布式的、高性能的基于决策树的梯度提升框架。
1、精度上:采用leaf-wise分裂,而XGB采用Layer-Wise生长;
2、计算上:大样本的计算优化(Gradient-based One-sided Sampling,GOSS);多特征计算优化(Exclusive Feature Building,EFB);并行化(分桶、最佳分裂并行化)
#先给定learning_rate=0.1
#给定初始参数
params = {'boosting_type':'gbdt',
'objective': 'binary',
'subsample': 0.8, # 数据采样
'colsample_bytree': 0.8} # 特征采样
gbm=lgb.LGBMClassifier(**params)
gbm.get_params()
params_1 = {'n_estimators':range(50,150,5)}
# GridSearchCV调参
cv = GridSearchCV(gbm,param_grid=params_1,scoring='roc_auc',cv=5)
grid_result = cv.fit(train_x, train_y)
print(grid_result.best_score_,grid_result.best_params_)
result = pd.DataFrame(grid_result.cv_results_)
plt.plot(result['param_n_estimators'],result['mean_test_score'])
params.update(grid_result.best_params_)
gbm=lgb.LGBMClassifier(**params)
param_2 = {'max_depth':range(5,9),'num_leaves ':range(20,50,2)}
cv = GridSearchCV(gbm,param_grid=param_2,scoring='roc_auc',cv=4)
grid_result = cv.fit(train_x, train_y)
print(grid_result.best_score_,grid_result.best_params_)
result = pd.DataFrame(grid_result.cv_results_)
params.update(grid_result.best_params_)
#params.update({'max_depth': 5, 'num_leaves ': 20})
gbm=lgb.LGBMClassifier(**params)
param_3 = {'min_child_samples':range(10,30,2),'min_child_weight':[i/1000 for i in range(0,20,2)]}
cv = GridSearchCV(gbm,param_grid=param_3,scoring='roc_auc',cv=4)
grid_result = cv.fit(train_x, train_y)
print(grid_result.best_score_,grid_result.best_params_)
result = pd.DataFrame(grid_result.cv_results_)
params.update(grid_result.best_params_)
#params.update({'min_child_samples': 10, 'min_child_weight': 0.0})
gbm=lgb.LGBMClassifier(**params)
param_4 = {'subsample':[i/10 for i in range(6,10,1)],'colsample_bytree':[i/10 for i in range(6,10,1)]}
cv = GridSearchCV(gbm,param_grid=param_4,scoring='roc_auc',cv=4)
grid_result = cv.fit(train_x, train_y)
print(grid_result.best_score_,grid_result.best_params_)
result = pd.DataFrame(grid_result.cv_results_)
params.update(grid_result.best_params_)
#params.update({'subsample': 0.6, 'subsample': 0.6})
gbm=lgb.LGBMClassifier(**params)
param_5 = {'reg_alpha':[i/10 for i in range(10)],'reg_lamb':[i/10 for i in range(10)]}
cv = GridSearchCV(gbm,param_grid=param_5,scoring='roc_auc',cv=4)
grid_result = cv.fit(train_x, train_y)
result = pd.DataFrame(grid_result.cv_results_)
print(grid_result.best_score_,grid_result.best_params_)
params.update(grid_result.best_params_)
#params.update({'reg_alpha': 0.0, 'reg_lamb': 0.0})
gbm=lgb.LGBMClassifier(**params)
param_6 = {'min_split_gain':[i/10 for i in range(10)]}
cv = GridSearchCV(gbm,param_grid=param_6,scoring='roc_auc',cv=4)
grid_result = cv.fit(train_x, train_y)
result = pd.DataFrame(grid_result.cv_results_)
print(grid_result.best_score_,grid_result.best_params_)
params.update(grid_result.best_params_)
#params.update({'min_split_gain': 0.0})
gbm=lgb.LGBMClassifier(**params)
#gbm.get_params()
param_7 = {'learning_rate':[i/100 for i in range(20)]}
cv = GridSearchCV(gbm,param_grid=param_7,scoring='roc_auc',cv=4)
grid_result = cv.fit(train_x, train_y)
print(grid_result.best_score_,grid_result.best_params_)
之后可以进行正常的训练等操作啦
params.update(grid_result.best_params_)
#params.update({'learning_rate': 0.01})
gbm=lgb.LGBMClassifier(**params)
#gbm.get_params()
gbm.fit(train_x, train_y) #训练
#y_pre = gbm.predict(train_x) #预测
#y_pre_prb = gbm.predict_proba(train_x) #预测概率值
y_pre = gbm.predict(test_x) #预测
y_pre_prb = gbm.predict_proba(test_x)
confusion_matrix(test_y,y_pre) #混淆矩阵
#classification_report(test_y,y_pre)
XGBoost(eXtreme Gradient Boosting)是Gradient Boosting算法的一个优化的版本。
Xgboost参数一般分为三类:
一、通用参数:宏观函数控制。
二、Booster参数:控制每一步的booster(tree/regression)。
三、学习目标参数:控制训练目标的表现。
Xgboost调参和LightGBM调参类似,本文就不再详述
# GridSearchCV调参
模型融合和集成学习区别:
如果硬要把集成学习进一步分类,可以分为两类,一种是把强分类器进行强强联合,使得融合后的模型效果更强,称为模型融合。另一种是将弱分类器通过学习算法集成起来变为很强的分类器,称为机器学习元算法。
模型融合的代表有:投票法(Voting)、线性混合(Linear Blending)、Stacking。而机器学习元算法又可以根据个体学习器之间是否存在依赖关系分为两类,称为Bagging和Boosting:
常见的模型融合方法:
#投票法(Voting)
'''
tree_model = DecisionTreeClassifier()
RF_model = RandomForestClassifier()
xgb_model = XGBClassifier()
LR_model = LogisticRegression() #需要标准化
GBM_model = GradientBoostingClassifier(n_estimators=50)
lgb_model = LGBMClassifier()
cat_model = CatBoostClassifier()
'''
vote_model = VotingClassifier(estimator=[('dt',tree_model),
('gbdt',GBM_model),
('lgb',lgb_model),
('xgb',xgb_model)], #list of (string, estimator) tuples
voting='soft', # str, {‘hard’, ‘soft’} (default=’hard’).
#分类的机器学习算法输出有两种类型:一种是直接输出类标签,另外一种是输出类概率,使用前者进行投票叫做硬投票(Majority/Hard voting),使用后者进行分类叫做软投票(Soft voting)。
#Hard Voting Classifier:根据少数服从多数来定最终结果;
#Soft Voting Classifier:将所有模型预测样本为某一类别的概率的平均值作为标准,概率最高的对应的类型为最终的预测结果;
weights=[1,1,2,2], #每个方法预先的权值,默认各方法权值相同.
flatten_transform=True)
#vote_model = vote_model.fit(train_x,train_y)
#y_pre = vote_model.predict(test_x)
#confusion_matrix(test_y,y_pre) #混淆矩阵,评估模型
#classification_report(test_y,y_pre)
for clf, clf_name in zip([tree_model, GBM_model, lgb_model, xgb_model,vote_model],['dt', 'gbdt', 'lgb', 'xgb','vote']):
scores = cross_val_score(clf, train_x, train_y, cv=5, scoring='accuracy')
print('Accuracy: {:.2f} (+/- {:.2f}) [{}]'.format(scores.mean(), scores.std(), clf_name))
Bagging(Booststrap Aggregating,装袋法)。
Bagging就是采用有放回的方式进行抽样,用抽样的样本建立子模型,对子模型进行训练,这个过程重复多次,最后进行融合。大概分为这样两步:
1.重复K次:
2.模型融合:
可达到减少方差的效果,例如随机森林。
from sklearn.ensemble import BaggingClassifier,BalancedBaggingClassifier
bagging_model = BalancedBaggingClassifier(base_estimator=lgb_model,
n_estimators=10, #生成10个模型
ratio='auto',
repalcement=False,
)
Boosting是一种串行方法,它的思想是一种迭代的方法,每一次训练的时候都更加关心分类错误的样例,给这些分类错误的样例增加更大的权重,下一次迭代的目标就是能够更容易辨别出上一轮分类错误的样例。最终将这些弱分类器进行加权相加。达到减少偏差的效果。例如:AdaBoost(Adaptive boosting)、GBDT(Gradient Boost Decision Tree)等。
Stacking(堆叠法),使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。非线性融合,Stacking相比Linear Blending来说,更加强大,然而也更容易过拟合。达到改进预测的效果。
stack_model = StackingClassifier(classifiers=[GBM_model, lgb_model, xgb_model], #基分类器,数组形式,[cl1, cl2, cl3]. 每个基分类器的属性被存储在类属性 self.clfs_.
use_probas=True,#bool (default: False) ,如果设置为True, 那么目标分类器的输入就是前面分类输出的类别概率值而不是类别标签
average_probas=False,#bool (default: False),用来设置上一个参数当使用概率值输出的时候是否使用平均值。
meta_classifier=lr) #目标分类器,即将前面分类器合起来的分类器
#verbose : int, optional (default=0)。用来控制使用过程中的日志输出,当 verbose = 0时,什么也不输出, verbose = 1,输出回归器的序号和名字。verbose = 2,输出详细的参数信息。verbose > 2, 自动将verbose设置为小于2的,verbose -2.
for clf, clf_name in zip([tree_model,
GBM_model,
lgb_model,
xgb_model,
vote_model,
stack_model],
['dt', 'gbdt', 'lgb', 'xgb','vote','stack']):
scores = cross_val_score(clf, train_x, train_y, cv=5, scoring='accuracy')
print('Accuracy: {:.2f} (+/- {:.2f}) [{}]'.format(scores.mean(),
scores.std(),
clf_name))
线性融合
用于回归
例如对数、平方根处理等;
自定义
k=[10,100,150,300]
data_cut = pd.cut(data[column].values,k,include_lowest=True) #被切分的类数组数据,注意必须是1维;k是分为几段
等宽
data_cut = pd.cut(data[column].values,k,lables=range(k)) #k是分为几段
等频
w=[1.0*i/k for i in range(k+1)]
w=data.describe(percentiles=w)[4:4+k+1]
w[0]=w[0]*(1-1e-10)
data2 = pd.cut(data[column].values,k,lables=range(k))
聚类
pred_y = model.predict(test_x)
pred_prb_y = model.predict_proba(test_x)
test = test_x
test['pred_y'] = pred_y
test['pred_prb_y_0'] = pred_prb_y[:,0]
test['pred_prb_y_1'] = pred_prb_y[:,1]
test.to_csv('test_predict.csv')
df = spark.createDataFrame(test) #data是python dataframe格式,要先转化
# 1、不写分区表,只是简单的导入到hive表
df.write.mode("overwrite").saveAsTable("databasename.tablename") #df是spark dataframe格式
# 2、或者使用每次重建分区表的方式
df.write.mode("overwrite").partitionBy("date").insertInto("ai.canser_test_predict_hive")
df.write.saveAsTable("ai.canser_test_predict_hive", None, "append", partitionBy='date')