/ MACHINELEARNING

机器学习常用函数

一.数据处理工具pandas和numpy

1.1 pandas读取数据

data = pd.read_csv("data.csv",index_col=False,encoding = "utf-8")
data = pd.read_tabel("data.txt",sep = ",")

1.2 numpy.random 生成数据的用法

numpy.random.rand(4,2,3)  ==>生成4*2*3的矩阵其中元素在[0,1)float
np.random.randn(4,2,3)  ==>生成4*2*3的矩阵元素是标准正态分布以0为均值以1为标准差的正态分布记为N01)),float
np.random.randint(-5,5,size=(2,2))  ==>生成一个2*2的矩阵元素值在[-5,5)随机整数int
np.random.random_sample(size=(2,2))  ==>生成一个2*2的矩阵元素是[0,1),float
np.random.seed(1676) ==>设置种子数每次生成的随机数相同

1.3 pandas_profiling

用于简单快速查看数据分布和得到数据报告。

import pandas_profiling
pfr = pandas_profiling.ProfileReport(data)
pfr.to_file("./example.html")

1.4 pandas去掉重复项 df.drop_duplicates()

df[df.duplicated()].shape
df = df.drop_duplicates()
df.shape

1.5 pandas中loc和iloc区别

  • loc利用index的名称(这里可以是index和行号不一致),来获取想要的行(或列)。(名称导向的这个特点,使得df[df.loc[‘col_name’] == ‘condition’, ‘col_name’] = value_1成立。 具体的实际应用,可参考 代码案例 一步实现EXCEL的合并数据、数据筛选、数据透视功能。

  • iloc利用index的具体位置(所以它只能是整数型参数行号),来获取想要的(或)。

# 这里loc就可以直接用自己写的索引来构成
df.loc['C':'6', '3':, -1] 

# 利用iloc抽取指定位置(所在的行整数值)的索引所构成的新的dataframe
new_dataframe = df.iloc[index_list,:]

1.6 找到Nan值——np.isnan()

nan_np_list = np.argwhere(np.isnan(np_data))

1.7 哑变量生成——pd.get_dummies()

dummy_device_type = pd.get_dummies(data_org['platform'],prefix='device_type')

1.8 计算特征之间的相关系数

自变量之间相关系数较大的话,需要考虑共线性的问题,共线性会导致模型出现开式解,降低模型的稳定性。

常见方法有皮尔森相关系数斯皮尔曼相关系数。两个系数都是介于-1和1之间,-1表示完全负相关,1表示完全正相关,0表示完全不相关。

使用皮尔森相关系数有局限:要求数据是成对的从正态分布中取得的。而斯皮尔曼相关系数是一种秩相关系数,不受数据分布的影响,它通过对变量排序,以排序后两个变量的秩次差来计算相关系数。

pearson = data.corr() # 适用于都是连续性变量
spearman = data.corr('spearman') # 适用于离散和连续变量

1.9 dataframe的拼接

df_all_row = concat([df1,df2])  #等价于 df1.append(df2),纵着拼接

#等价于 merge(df1,df2,left_index=True,right_index=True,how='outer')
df_all_col = concat([df1,df2],axis=1) # 横着拼接

1.10 groupby的使用

df = pd.DataFrame({'A': ['a', 'b', 'a', 'c', 'a', 'c', 'b', 'c'], 
                   'B': [2, 8, 1, 4, 3, 2, 5, 9], 
                   'C': [102, 98, 107, 104, 115, 87, 92, 123]})
df.groupby('A').mean()
==>     
A   B       C                 
a  2.0  108.000000
b  6.5   95.000000
c  5.0  104.666667

1.11 Series.apply

该函数用于对该series的所有元素进行处理生成一个新的series。

new_series = pd.Series([i for i in range(10)]).apply(lambda x:x**2)

"""这里是函数中带2个参数的"""
def subtract_custom_value(x, custom_value):
    return x - custom_value
new_series_2 = df.apply(subtract_custom_value, args=(5,))

1.12 Series可以直接用于2个列相加减

a = pd.Series([i for i in range(10)])
b = pd.Series([i+1 for i in range(10)])
diff_series = a - b

1.13 sort_values将dataframe根据某一列顺序重新生成

# 比如这里需要将整个dataframe根据时间戳的顺序(True)进行重新调整
data = data.sort_values(by = ['timestamp']ascending=True)

1.14 concat 将Dataframe或者是Series进行合并

data = pd.concat([x1,x2,x3],axis=1) # 这里是三个Series根据每个的index进行合并(按列)

1.15 Series.reset_index 直接将Series转成Dataframe

df = series.reset_index(name = 'index_name')  # 这里给series的index设置名字为'index_name',并变成一列

1.16 df.groupby()的apply方式使用

# 初始的dataframe
df = pd.DataFrame({'A': 'a a b'.split(), 'B': [1,2,3], 'C': [4,6, 5]})
g = df.groupby('A')
print(g.apply(lambda x: x / x.sum()))
         B    C
0  0.333333  0.4
1  0.666667  0.6
2  1.000000  1.0

print(g.apply(list))
      B    C
0  [1,2]  [3]
1  [4,6]  [5]

1.17 df.groupby() 直接分成2个组的dataframe

df = pd.DataFrame({'A': 'a a b'.split(), 'B': [1,2,3], 'C': [4,6, 5]})
g = df.groupyby('A')
for name,group in g:
    name_i = name
    df_i = group # 这里就是A只有a的dataframe

二.绘图查看数据分布——seaborn和matplotlib

2.1 频数分布直方图

def plot_bar(x,y,color,title,width = 0.5):
    plt.figure()
    idx = np.arange(len(x))
    plt.bar(idx,y,width,color = color)
    for xx, yy in zip(x, y):
        plt.text(xx, yy + 0.1, str('%.2f%%' % 			          ((yy/np.array(y).sum())*100)), ha='center')
    plt.xticks(idx,x)
    plt.title(title)
    plt.xlabel('Hour')
    plt.ylabel('Trade-Frequence')
    plt.show()
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

# the histogram of the data
n, bins, patches = plt.hist(x, 50, density=1, facecolor='g', alpha=0.75)


plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()

2.2 散点图

plt.plot(x,y)

2.3 直线图

plt.scatter(x,y)

2.4 双变量分布图

def two_dims_draw_relationship(df,xlabel,ylabel):
    # 双变量分布 x,ylabel是字符串,df必须是双维度的dataframe
    sns.set(color_codes=True)
    g = sns.jointplot(x=xlabel, y=ylabel, data=df, kind="kde", color="y")
    g.plot_joint(plt.scatter, c="m", s=30, linewidth=1, marker="+")
    g.ax_joint.collections[0].set_alpha(0)  # 画背景网格线
    g.set_axis_labels("${}$".format(xlabel), "${}$".format(ylabel))
    plt.show()

2.5 多变量两两之间的分布图

def all_two_feature_distribution(df = sns.load_dataset('iris')):
    sns.set(style="ticks")
    sns.pairplot(df, hue="species")
    plt.show()

2.6 热度图

scores_h = pd.DataFrame(np.array(scores_h).reshape(18, 3))
scores_h.index = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
scores_h.columns = [1,2,3]
plt.figure()
ax = sns.heatmap(scores_h, annot=True,xticklabels=cols_all_features,
                 yticklabels=cols_all_features,fmt='.2f')
plt.ylabel("N_cluster")
plt.xlabel("linkages")
# 必须先savefig,之后再show,就不会出现保存时白色图片了
plt.savefig("h.jpg")
plt.show()

三.机器学习包sklearn

3.1 划分数据集

from sklearn.model_selection import train_test_split
(trainX,testX,trainY,testY) = train_test_split(X,y,test_size=0.2,random_state=42)

3.2 特征标准化

  • 标准化:使用scale模块直接计算标准化,将标准化的array放在x_scale中,同时可以查看均值和标准差,但是该方式的一个不足是当存在新的样本到来时,无法利用已有的模块直接复用,需要利用mean和std自己计算。
    x_scale = preprocessing.scale(DatMat)  
    x_scale.mean(axis=0)
    x_scale.std(axis=0)
    
  • 归一化:使用StandardScaler模块计算标准化,可以利用训练集数据建立一个转化的类,类似于实现将mean和std存储在该类中,将数据输入,就可以直接求出结果。
    scaler = preprocessing.StandardScaler().fit(datingDatMat)
    datingDatMat = scaler.transform(datingDatMat)
    new_date = numpy.array([1, 2, 3])
    new_date_std = scaler.transform(new_date.reshape(1, -1))
    

    这里的scaler更象是扮演一个计算器的角色,本身并不存储数据。

3.3 交叉验证——查验模型稳定性

from sklearn.model_selection import cross_val_score
 model_stability = cross_val_score(model,
                              trainX,trainY,cv=10,scoring="accuracy")
mean_score_model = model_stability.mean()

3.4 模型评估方式——混淆矩阵

from sklearn.metrics import confusion_matrix
print(confusion_matrix(testY,y_pred))

3.5 分类结果展示(准确性,召回率,f1-score)

from sklearn.metrics import classification_report
print(confusion_matrix(testY,y_pred))

3.6 模型的保存和加载

import pickle
# 保存模型
pickle.dump(rf_clf, open('model/model.model', 'wb'))
# 导入模型
model = pickle.load(open('model_save/model.model','wb'))

3.7 数据样本不均衡——SMOTEENN

from imblearn.combine import SMOTEENN
smote_enn = SMOTEENN(random_state=42)
X_resampled,y_resampled = smote_enn.fit_sample(X,y)

3.8 自动超参调节

  • 自动调参——GridSearchCV
from sklearn.model_selection import GridSearchCV
rcl=RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features='sqrt',random_state=10)
# 现在不确定RandomForest其中一个参数n_estimators的个数
param_test1 = {'n_estimators':range(10,71,10)}
gsearch1= GridSearchCV(estimator =rcl,param_grid=                                              param_test1,scoring='roc_auc',cv=5)
gsearch1.fit(X,y)
print(gsearch1.grid_scores_, gsearch1.best_params_, 	           gsearch1.best_score_)
  • 自动调参神器——Hyperopt
from hyperopt import fmin, tpe, hp, rand
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn import svm
from sklearn import datasets

# SVM的三个超参数:C为惩罚因子,kernel为核函数类型,gamma为核函数的额外参数(对于不同类型的核函数有不同的含义)
# 有别于传统的网格搜索(GridSearch),这里只需要给出最优参数的概率分布即可,而不需要按照步长把具体的值给一个个枚举出来
parameter_space_svc ={
    # loguniform表示该参数取对数后符合均匀分布
    'C':hp.loguniform("C", np.log(1), np.log(100)),
    'kernel':hp.choice('kernel',['rbf','poly']),
    'gamma': hp.loguniform("gamma", np.log(0.001), np.log(0.1)),
}

# 鸢尾花卉数据集,是一类多重变量分析的数据集
# 通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类
iris = datasets.load_digits()

#--------------------划分训练集和测试集--------------------
train_data = iris.data[0:1300]
train_target = iris.target[0:1300]
test_data = iris.data[1300:-1]
test_target = iris.target[1300:-1]
#-----------------------------------------------------------

# 计数器,每一次参数组合的枚举都会使它加1
count = 0

def function(params):
    c = params["C"]
    kernel = params["kernel"]
    gamma = params["gamma"]

    # **可以把dict转换为关键字参数,可以大大简化复杂的函数调用
    clf = svm.SVC(C=c,kernel = kernel,gamma = gamma)

    # 训练模型
    clf.fit(train_data,train_target)

    # 预测测试集
    prediction = clf.predict(test_data)

    global count
    count = count + 1
    score = accuracy_score(test_target,prediction)
    print("第%s次,测试集正确率为:" % str(count),score)

    # 由于hyperopt仅提供fmin接口,因此如果要求最大值,则需要取相反数
    return -score

# algo指定搜索算法,目前支持以下算法:
# ①随机搜索(hyperopt.rand.suggest)
# ②模拟退火(hyperopt.anneal.suggest)
# ③TPE算法(hyperopt.tpe.suggest,算法全称为Tree-structured Parzen Estimator Approach)
# max_evals指定枚举次数上限,即使第max_evals次枚举仍未能确定全局最优解,也要结束搜索,返回目前搜索到的最优解
best = fmin(function, parameter_space_svc, algo=tpe.suggest, max_evals=100)

# best["kernel"]返回的是数组下标,因此需要把它还原回来
kernel_list = ['rbf','poly']
best["kernel"] = kernel_list[best["kernel"]]

print("最佳参数为:",best)

clf = svm.SVC(**best)
print(clf)

3.9 to_categorical

功能:将label转为one_hot形式,源于keras.utils包

from keras.utils import to_categorical
y_onehot = to_categorical(y,num_classes(总类别数))

3.10 绘制ROC曲线

from sklearn.metrics import roc_curve, auc
def draw_ROC_curve(y_test, y_predict, savepath):
    '''画ROC曲线'''
    false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_predict)
    roc_auc = auc(false_positive_rate, true_positive_rate)
    plt.title('ROC')
    plt.plot(false_positive_rate, true_positive_rate, 'b', label='AUC = %0.2f' % roc_auc)
    plt.legend(loc='lower right')
    plt.plot([0, 1], [0, 1], 'r--')
    plt.ylabel('TPR')
    plt.xlabel('FPR')
    plt.savefig(savepath)
    plt.show()
    plt.close(0)

四.分类模型

4.1 随机森林

from sklearn.ensemble import RandomForestClassifier
rf_clf = RandomForestClassifier(n_estimators=700
,n_jobs=-1,max_leaf_nodes=30)
rf_clf.fit(trainX,trainY)
y_pred = rf_clf.predict(testX)
# 特征重要性
feature_importance = rf_clf.feature_importances_

4.2.Xgboost

优势:表现快,训练时可以用所有的 CPU 内核来并行化建树;用分布式计算来训练非常大的模型;对于非常大的数据集还可以进行 Out-of-Core Computing)。参数:learning_rate = 0.1 或更小,越小就需要多加入弱学习器;tree_depth = 2~8;subsample = 训练集的 30%~80%。

from xgboost import XGBClassifier
model = XGBClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
# 可以在每加入一颗树后打印出 logloss
eval_set = [(X_test, y_test)]
model.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="logloss", eval_set=eval_set, verbose=True)
# 输出特征重要性
from xgboost import plot_importance
from matplotlib import pyplot
plot_importance(model)
pyplot.show()

4.3 SVM

from sklearn.svm import SVC
clf = SVC(gamma='auto',C,kernel = "RBF")
clf.fit(X, y)
y_pred = clf.predict(testX)

五.聚类模型

5.1.轮廓系数

评估聚类效果好坏——轮廓系数(Silhouette Coefficient)结合了聚类的凝聚度(Cohesion)和分离度(Separation),用于评估聚类的效果。该值处于-1~1之间,值越大,表示聚类效果越好。

#聚类评估:轮廓系数
from sklearn.metrics import silhouette_score
# Kmeans的聚类结果来进行测试
labels = KMeans(n_clusters=k).fit(data).labels_
score = silhouette_score(data, labels)