美赛建模总体思路

总体思路

1. 数据处理

空值处理(nan值)填补方法:拉格朗日插值,均值填补,众数填补,回归填补,k-means填补,或直接删掉空值
特征转换,例如one-hot,文本转数值(bag of words)
归一化:把数据缩到0到1之间,正态化例如softmax
样本点少的可以删除

2. 预分析

2.1 画图

热力图
小提琴图
散点矩阵图
多元散点图
Hexbin图
界定相关数据,并且进行直观的观察和分析(画图观察数据(画图多样性:词云图,box plot))),寻找建模所用的特征,判断有无相关关系

2.2 特征分类

特征分类:
(1)长期特征:提前3个月得到的确定值
(2)短期特征:不能提前3个月获取值的特征
聚类(分类)模型:
k-means代表连续型数据集
k-mode用于离散型数据集
dbscan用来做分类的,用于连续型,比如一个班的同学都在一起就可以看作一类

3. 建模

经过多次实验对多个模型进行检验,选择合适的模型,并进一步对特征进行选择(有些特征可能用处不大,可PCA降维)

3.1. 过拟合处理方法

3.1.1. 特征选择

在这里插入图片描述

Filter方法

先对数据集进行特征选择,然后再训练模型。该方法独立于模型本身,因为比wrapper方法更general,计算性能更好,所以有时候在Wrapper前先用它。

  • 皮尔逊相关系数 Pearson Correlation(就是我们统计学的那个相关系数)
    一般只用于线性关系的判断。

    	from scipy.stats import pearsonr
    	import numpy as np
    	pccs = np.corrcoef(x, y) # numpy的函数 或
    	pccs = pearsonr(x, y) # scipy.stats的函数
    
  • 互信息和最大信息系数 Mutual information and maximal information coefficient (MIC)

    1. MIC可以识别各种函数关系,例如:正弦函数和双曲线函数和直线。
    2. 如果没有噪音的直线关系和没有噪音的正弦函数关系,他们的MIC都是1,加上相同的噪音之后,如果线性关系的MIC变成0.7了,那么正弦函数关系的MIC也变成0.7,换句话说,噪音对MIC造成的影响与变量之间的函数关系无关,但这一论证在一篇论文中被反驳了,或者说部分反驳了。
    import numpy as np
    from minepy import MINE
    
    def print_stats(mine):
        print("MIC", mine.mic()) # 返回MIC
    
    x = np.linspace(0, 1, 1000)
    y = np.sin(10 * np.pi * x) + x
    mine = MINE(alpha=0.6, c=15)
    mine.compute_score(x, y)
    
    print("Without noise:")
    print_stats(mine)
    print()
    
    np.random.seed(0)
    y += np.random.uniform(-1, 1, x.shape[0])  # add some noise
    mine.compute_score(x, y)
    
    print("With noise:")
    print_stats(mine)
    
  • 距离相关系数 (Distance correlation)
    为了克服皮尔逊相关系数的弱点,即使皮尔逊相关系数=0,这两个变量可能是非线性相关,但如果距离相关稀疏为0,那么这两个变量就是独立的了。dcorr(u,v)越大,u和v的相关性越强
    在这里插入图片描述

    from scipy.spatial.distance import pdist, squareform
    import numpy as np
    
    def distcorr(X, Y):
        """ Compute the distance correlation function
    
        # >>> a = [1,2,3,4,5]
        # >>> b = np.array([1,2,9,4,4])
        # >>> distcorr(a, b)
        0.762676242417
        """
        X = np.atleast_1d(X)
        Y = np.atleast_1d(Y)
        if np.prod(X.shape) == len(X):
            X = X[:, None]
        if np.prod(Y.shape) == len(Y):
            Y = Y[:, None]
        X = np.atleast_2d(X)
        Y = np.atleast_2d(Y)
        n = X.shape[0]
        if Y.shape[0] != X.shape[0]:
            raise ValueError('Number of samples must match')
        a = squareform(pdist(X))
        b = squareform(pdist(Y))
        A = a - a.mean(axis=0)[None, :] - a.mean(axis=1)[:, None] + a.mean()
        B = b - b.mean(axis=0)[None, :] - b.mean(axis=1)[:, None] + b.mean()
    
        dcov2_xy = (A * B).sum() / float(n * n)
        dcov2_xx = (A * A).sum() / float(n * n)
        dcov2_yy = (B * B).sum() / float(n * n)
        dcor = np.sqrt(dcov2_xy) / np.sqrt(np.sqrt(dcov2_xx) * np.sqrt(dcov2_yy))
        return dcor
    
    
    a = [1,2,3,4,5]
    b = np.array([1,2,9,4,4])
    dcor = distcorr(a, b)
    print(dcor)
    
  • 基于学习模型的特征排序 (Model based ranking)

Wrapper方法

直接把最终将要使用的模型的性能作为特征子集的评价标准

  • SBS:从特征全集里逐个去除单个特征,直至剩余的特征子集达到期望的维度。那么如何逐个去除呢?我们先定义一个标准函数J(选一个metrics score如accuracy score),借助J的变化来判断每一步应该去除哪个特征。
    • 如果metric score越大越好,那么判断标准就是:当去除一个特征带来accuracy score增加得最多时(accuracy score降低时取降低得最少),去除该特征。
    • 如果metric score越小越好(RMSE),那么判断标准就是:当去除一个特征带来accuracy score降低得最多(增加得最少)时,我们就去除这个特征。
    • 总结:每一步选择去掉的是最不会导致模型变更差的那个特征。
  • sklearn中的RFE (Recursive feature elimination)的主要思路是反复构建模型(如SVM或者回归模型)然后选出最好的(或者最差的)的特征(可以根据系数来选),把选出来的特征放到一边,接着在剩余的特征上重复以上过程,直到遍历了所有特征。类似SBS的思路。
    from sklearn.feature_selection import RFE
    from sklearn.linear_model import LinearRegression
    from sklearn.datasets import load_boston
    
    boston = load_boston()
    X = boston["data"]
    Y = boston["target"]
    names = boston["feature_names"]
    
    #use linear regression as the model
    lr = LinearRegression()
    #rank all features, i.e continue the elimination until the last one
    rfe = RFE(lr, n_features_to_select=1)
    rfe.fit(X,Y)
    
    print("Features sorted by their rank:")
    print(sorted(zip(rfe.ranking_, names)))
    
  • 稳定性选择:sklearn中的RSM (Randomized sparse models)其主要思想是在不同的数据子集和特征子集上运行特征选择算法,不断的重复,最终汇总特征选择结果,比如可以统计某个特征被认为是重要特征的频率(被选为重要特征的次数除以它所在的子集被测试的次数)。越重要的特征的得分会越接近1。
    from sklearn.linear_model import RandomizedLasso
    from sklearn.datasets import load_boston
    boston = load_boston()
    
    #using the Boston housing data. 
    #Data gets scaled automatically by sklearn's implementation
    X = boston["data"]
    Y = boston["target"]
    names = boston["feature_names"]
    
    rlasso = RandomizedLasso(alpha=0.025)
    rlasso.fit(X, Y)
    
    print("Features sorted by their score:")
    print(sorted(zip(map(lambda x: format(x, '.4f'), rlasso.scores_), names), reverse=True))
    
Embedded方法
  • 线性模型和正则化:
    • 线性模型
      • 越重要的特征对应的系数就会越大,而跟输出变量越是无关的特征对应的系数就会越接近于0,起相反作用的特征对应的系数是小于0。
        from sklearn.linear_model import LinearRegression
        import numpy as np
        
        # A helper method for pretty-printing linear models
        def pretty_print_linear(coefs, names=None, sort=False):
            if names == None:
                names = ["X%s" % x for x in range(len(coefs))]
            lst = zip(coefs, names)
            if sort:
                lst = sorted(lst, key=lambda x: -np.abs(x[0]))
            return " + ".join("%s * %s" % (round(coef, 3), name) for coef, name in lst)
        
        np.random.seed(0)  # 有了这段代码,下次再生成随机数的时候,与上次一样的结果
        size = 5000  # 表示抽取多少个样本
        # 随机生成3个特征的样本,每个维度的特征都是服从期望为0,标准差为1的正态分布
        X = np.random.normal(0, 1, (size, 3))  # 抽取5000个样本,每个样本都是3维的
        # Y = X0 + 2*X1 + noise
        Y = X[:, 0] + 2 * X[:, 1] + np.random.normal(0, 2, size)
        lr = LinearRegression()
        lr.fit(X, Y)
        
        print("Linear model:", pretty_print_linear(lr.coef_))
        
      • 多重共线性问题:在很多实际的数据当中,往往存在多个互相关联(X1≈X2)的特征,这时候模型就会变得不稳定,对噪声很敏感,数据中细微的变化就可能导致模型的巨大变化
      size = 100
      # 另外一个种子为5的随机采样,若要执行相同的结果,以种子号来区分随机采样的结果
      np.random.seed(seed=5)  
      X_seed = np.random.normal(0, 1, size)
      
      X1 = X_seed + np.random.normal(0, .1, size)
      X2 = X_seed + np.random.normal(0, .1, size)
      X3 = X_seed + np.random.normal(0, .1, size)
      
      X = np.array([X1, X2, X3]).T
      Y = X1 + X2 + X3 + np.random.normal(0, 1, size)
      
      lr = LinearRegression()
      lr.fit(X, Y)
      print("Linear model:", pretty_print_linear(lr.coef_))
      
      答案:>>> Linear model: -1.291 * X0 + 1.591 * X1 + 2.747 * X2
    • **L1正则化(Lasso Regression)的特点是迫使那些弱的特征所对应的系数为0,**因此L1正则化往往会使学到的模型很稀疏。这既是优点也是缺点,看情况而定。
      from sklearn.linear_model import Lasso
      from sklearn.preprocessing import StandardScaler
      from sklearn.datasets import load_boston
      import numpy as np
      
      boston = load_boston()
      scaler = StandardScaler()
      X = scaler.fit_transform(boston["data"])
      Y = boston["target"]
      names = boston["feature_names"]
      
      lasso = Lasso(alpha=.3)
      lasso.fit(X, Y)
      print("Lasso model: ", pretty_print_linear(lasso.coef_, names, sort=True))
      
    • L2正则化(Ridge Regression)让系数的取值变得平均,较为稳定,系数不太会因为细微的数据变化而波动,不像L1正则化那样。可以处理多重共线性
      import numpy as np
      from sklearn.linear_model import LinearRegression
      from sklearn.linear_model import Ridge
      
      size = 100
      # We run the method 10 times with different random seeds
      for i in range(10):
          print("Random seed %s" % i)
          np.random.seed(seed=i)
          X_seed = np.random.normal(0, 1, size)
          X1 = X_seed + np.random.normal(0, .1, size)
          X2 = X_seed + np.random.normal(0, .1, size)
          X3 = X_seed + np.random.normal(0, .1, size)
          Y = X1 + X2 + X3 + np.random.normal(0, 1, size)
          X = np.array([X1, X2, X3]).T
          lr = LinearRegression()
          lr.fit(X, Y) # 普通LR
          print("Linear model:", pretty_print_linear(lr.coef_))
          ridge = Ridge(alpha=10)
          ridge.fit(X, Y) # L2
          print("Ridge model:", pretty_print_linear(ridge.coef_))
      
    • 树算法
      • 随机森林
        • 平均不纯度减少(mean decrease impurity)
          随机森林由多个决策树构成。利用不纯度可以确定节点(最优条件),对于分类问题,通常采用基尼不纯度或者信息增益,对于回归问题,通常采用的是方差或者最小二乘法拟合。当训练决策树的时候,可以计算出每个特征减少了多少树的不纯度。对于一个决策树森林来说,可以算出每个特征平均减少了多少不纯度,并把它平均减少的不纯度作为特征选择的值。
          from sklearn.datasets import load_boston
          from sklearn.ensemble import RandomForestRegressor
          import numpy as np
          
          #Load boston housing dataset as an example
          boston = load_boston()
          X = boston["data"]
          Y = boston["target"]
          names = boston["feature_names"]
          rf = RandomForestRegressor()
          rf.fit(X, Y)
          print("Features sorted by their score:")
          print(sorted(zip(map(lambda x: "%.4f"%x, rf.feature_importances_), names), reverse=True))
          
        • 平均精确率减少 (mean decrease accuracy)
          1. 这种方法直接度量每个特征对模型精确率的影响。
          2. 主要思路:打乱每个特征的特征值顺序,并且度量顺序变动对模型的精确率的影响。对于不重要的变量来说,打乱顺序对模型的精确率影响不会太大;对于重要的变量来说,打乱顺序就会降低模型的精确率。
          from sklearn.model_selection import ShuffleSplit
          from sklearn.metrics import r2_score
          from sklearn.datasets import load_boston
          from collections import defaultdict
          from sklearn.ensemble import RandomForestRegressor
          import numpy as np
          
          boston = load_boston()
          X = boston["data"]
          Y = boston["target"]
          names = boston["feature_names"]
          
          rf = RandomForestRegressor()
          scores = defaultdict(list)
          # crossvalidate the scores on a number of different random splits of the data
          rs = ShuffleSplit(len(X), 100, .3)
          for train_idx, test_idx in rs.split(X):
              X_train, X_test = X[train_idx], X[test_idx]
              Y_train, Y_test = Y[train_idx], Y[test_idx]
              r = rf.fit(X_train, Y_train)
              acc = r2_score(Y_test, rf.predict(X_test))
              for i in range(X.shape[1]):
                  X_t = X_test.copy()
                  np.random.shuffle(X_t[:, i])
                  shuff_acc = r2_score(Y_test, rf.predict(X_t))
                  scores[names[i]].append((acc - shuff_acc) / acc)
          print("Features sorted by their score:")
          print(sorted( [(float('%.4f'%np.mean(score)), feat) for
                        feat, score in scores.items()], reverse=True) )
          
      • 决策树
        • ID3(只用于连续型),C4.5,CART树
3.1.2. 降维
  • PCA (KPCA)
  • SVD

对无label数据的处理思路:
通过无监督的方式先分类,再手动给标签,然后进行有监督学习
直接手动标记(annotation),进行有监督学习

4. 评价

层次分析法(AHP)
AIC
BIC

5. 优缺点

参考文章:

机器学习的特征选择方法总结
sklearn里的特征选择方法
特征选择方法—Filter,Wrapper,Embedded
基于模型的特征选择详解 (Embedded & Wrapper)
请叫我Mr. Unbelievable——预测北京市每日车辆事故率
特征选择, 经典三刀
Minepy—使用python计算最大互信息系数(MIC)
特征工程之距离相关系数( Distance correlation coefficient )
Distance correlation(距离相关系数)
常用距离算法和相关系数及其Python实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值