精华内容
下载资源
问答
  • 这是楼主自己学习过程中整理的机器学习实战全书的全部源代码,书上的代码有很多不能运行的,楼主把全部代码重新进行的书写,所有代码在python3上均通过运行,没有任何bug。全网唯一一个可以在python3下完美运行的...
  • 本代码主要利用Python工具实现SVD简化数据,简单明了,易于理解
  • 《Python 3数据分析与机器学习实战》自测练习答案
  • logistic回归的因变量可以是二分类的,也可以是多分类的,但是二分类的更为常用,也更加容易解释,多类可以使用softmax方法进行处理。实际中最为常用的就是二分类的logistic回归
  • 机器学习实战-思维导图,共15张思维导图,K近临、决策树、 朴素贝叶斯、SVM、树回归等
  • 有些地方中文显示不了,大部分还是可用的,斯坦福大学Andrew Ng的机器学习课程,很不错的
  • 机器学习实战图书对应的源码于数据集,git官网最新的代码和数据集。
  • 机器学习实战第三章决策树代码,说实话感觉这一章不太实用
  • 资料列表:代码,数字识别数据集,约会对象数据集 代码功能:代码使用kNN方法实现了对约会对象的分类,手写字体的识别,并切定义 了分类错误率的函数。
  • 机器学习实战--泰坦尼克号预测案例

    千次阅读 多人点赞 2018-08-22 14:12:16
    其实,泰坦尼克的预测案例网上有很多,只是那些都没有自己亲手去做,大致看了一下思路,毕竟这是自己的第一个实战项目,很有必要记录下来, 待以后学的更深的时候,看能不能改进模型的准确率。好了,废话不多说了。...

    其实,泰坦尼克的预测案例网上有很多,只是那些都没有自己亲手去做,大致看了一下思路,毕竟这是自己的第一个实战项目,很有必要记录下来, 待以后学的更深的时候,看能不能改进模型的准确率。好了,废话不多说了。开始吧。


    一、关于泰坦尼克号之灾

    泰坦尼克号的这个实战案例来自kaggle,上面是它的基本介绍情况。

    二、很重要的经验

    • 『对数据的认识太重要了!』
    • 『数据中的特殊点/离群点的分析和处理太重要了!』
    • 『特征工程(feature engineering)太重要了!在很多Kaggle的场景下,甚至比model本身还要重要』
    • 『要做模型融合(model ensemble)!』

    (注:这个总结是寒老师的总结,这里我就直接用了) 

    三、实战项目 

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import metrics
    from sklearn.linear_model import LogisticRegression

     step1:数据理解和探索

    train_df = pd.read_csv('train.csv')
    train_df.info()
    train_df.head(20)
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 891 entries, 0 to 890
    Data columns (total 12 columns):
    PassengerId    891 non-null int64
    Survived       891 non-null int64
    Pclass         891 non-null int64
    Name           891 non-null object
    Sex            891 non-null object
    Age            714 non-null float64
    SibSp          891 non-null int64
    Parch          891 non-null int64
    Ticket         891 non-null object
    Fare           891 non-null float64
    Cabin          204 non-null object
    Embarked       889 non-null object
    dtypes: float64(2), int64(5), object(5)
    memory usage: 83.6+ KB

    从信息中可以看出,年龄的值有缺失值,cabin(客舱)的缺失值更多,Embarked(码头)仅仅只有2个缺失值

    数据探索

    #### 查看Survived与Pclass的关系
    Survived_Pclass=train_df['Pclass'].groupby(train_df['Survived'])
    Survived_Pclass.value_counts().unstack()
    
    Survived_Pclass.value_counts().unstack().plot(kind='bar',stacked = True)
    plt.show()

     

     从图中可以看出,Pclass与获救程度有一定的相关性,获救的部分中接近一半的人数来自1号船舱,而未获救的人数主要来自3号船舱,且 未获救的人中来自1号船舱的非常少

    #### 查看Survived与Sex的关系
    
    Survived_Sex=train_df['Sex'].groupby(train_df['Survived'])
    Survived_Sex.value_counts().unstack()
    
    Survived_Sex.value_counts().unstack().plot(kind='bar',stacked=True)
    plt.show()

    说明性别对是否获救有很大的关系,未获救的人中绝大多数是男性。女性很少,获救的人中女性占了大部分的比例

    #### 查看Survived与Age的关系
    首先要对缺失值处理

    train_df['Age']=train_df['Age'].fillna(train_df['Age'].mean())
    train_df.info()
    
    train_age = pd.cut(train_df['Age'],bins =[0,5,15,20,35,50,60,100])
    train_age
    
    survie_age =pd.DataFrame(train_df['Survived'].values,train_age,columns = ['Survived',])
    
    survie_age.head(10)
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 891 entries, 0 to 890
    Data columns (total 12 columns):
    PassengerId    891 non-null int64
    Survived       891 non-null int64
    Pclass         891 non-null int64
    Name           891 non-null object
    Sex            891 non-null object
    Age            891 non-null float64
    SibSp          891 non-null int64
    Parch          891 non-null int64
    Ticket         891 non-null object
    Fare           891 non-null float64
    Cabin          204 non-null object
    Embarked       889 non-null object
    dtypes: float64(2), int64(5), object(5)
    memory usage: 83.6+ KB
    
    0      (20, 35]
    1      (35, 50]
    2      (20, 35]
    3      (20, 35]
    4      (20, 35]
    5      (20, 35]
    6      (50, 60]
    7        (0, 5]
    8      (20, 35]........
    
    ### 利用交叉表crosstab
    
    pd.crosstab(train_age,train_df['Survived'])
    
    pd.crosstab(train_age,train_df['Survived']).plot(kind='bar',stacked=True)
    pd.crosstab(train_age,train_df['Survived']).plot(kind='bar')
    plt.show()

    从图中可以看出,孩子的优先级比较高,未获救的相对来说比较少,其中20-35岁之间未获救的人数特别多

    step2:数据准备

    train_x = train_df[['Pclass','Sex','Age','SibSp','Parch','Fare']]
    train_y = train_df['Survived']
    train_x.info()
    train_x.head()
    
    train_x['Sex']=train_x['Sex'].replace({'male':1,'female':0})
    train_x.info()
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 891 entries, 0 to 890
    Data columns (total 6 columns):
    Pclass    891 non-null int64
    Sex       891 non-null int64
    Age       891 non-null float64
    SibSp     891 non-null int64
    Parch     891 non-null int64
    Fare      891 non-null float64
    dtypes: float64(2), int64(4)
    memory usage: 41.8 KB
    # 构建第一个分类模型,利用LR模型
    lr = LogisticRegression()
    lr.fit(train_x,train_y)
    
    print(lr.coef_)
    pd.DataFrame(list(zip(np.transpose(lr.coef_),train_x.columns)),columns=['coef_','names'])
    
    lr.score(train_x,train_y)

    Out[69]:

    LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
              intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
              penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
              verbose=0, warm_start=False)

    Out[72]:

    0.7991021324354658

    尝试其他的分类算法 

    from sklearn.linear_model import LogisticRegression
    from sklearn.svm import LinearSVC
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.tree import DecisionTreeClassifier
    
    names = ['LogisticRegression','LinearSVC','KNeighborsClassifier','RandomForestClassifier','DecisionTreeClassifier']
    clfs =[LogisticRegression(),LinearSVC(),KNeighborsClassifier(n_neighbors=3),RandomForestClassifier(),DecisionTreeClassifier()]
    for name,clf in zip(names,clfs):
        clf.fit(x_train,y_train)
        print(clf)
        print("train_score:",clf.score(x_train,y_train))
        y_pre = clf.predict(x_test)
        test_score = metrics.accuracy_score(y_pre,y_test)
        print("test_score:",test_score)
        print('\n')
    LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
              intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
              penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
              verbose=0, warm_start=False)
    train_score: 0.799357945425
    test_score: 0.791044776119
    
    
    LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
         intercept_scaling=1, loss='squared_hinge', max_iter=1000,
         multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
         verbose=0)
    train_score: 0.735152487961
    test_score: 0.776119402985
    
    
    KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
               metric_params=None, n_jobs=1, n_neighbors=3, p=2,
               weights='uniform')
    train_score: 0.821829855538
    test_score: 0.705223880597
    
    
    RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                max_depth=None, max_features='auto', max_leaf_nodes=None,
                min_impurity_decrease=0.0, min_impurity_split=None,
                min_samples_leaf=1, min_samples_split=2,
                min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
                oob_score=False, random_state=None, verbose=0,
                warm_start=False)
    train_score: 0.963081861958
    test_score: 0.798507462687
    
    
    DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
                max_features=None, max_leaf_nodes=None,
                min_impurity_decrease=0.0, min_impurity_split=None,
                min_samples_leaf=1, min_samples_split=2,
                min_weight_fraction_leaf=0.0, presort=False, random_state=None,
                splitter='best')
    train_score: 0.980738362761
    test_score: 0.753731343284

    很显然,决策树和随机森林都发生了严重的过拟合,k近林也有稍许的过拟合,只有逻辑回归在训练集和测试集上两者的差异不是特别明显,因此这里认为逻辑回归取得了较好的效果.

    接下来,可以尝试做更多的特征来进行拟合,即我们说的特征工程,再接着,我们不妨尝试下各种模型的融合和参数调优。

    特征工程 --准备一个更好的数据集

    • 从1.构建第一个分类模型.ipynb的训练中可以看出,Pclass,Sex,Age对模型应该有很大的关系,其中从图中我们可以看出,经过离散化后,比如age<10(孩子)获救的机会很大,而 age>60则获救的机会不大,因此,年龄我们可以试想经过离散化后,新增成一个特征
    • 还有一个问题,从1.构建第一个分类模型的逻辑回归的系数中,我们发现
      [-0.82762531292] Pclass 呈现负相关;  
      [-2.51023957603] Sex 呈现负相关; 
      [-0.0288397831037] Age 呈现负相关,其实我们从最开始的数据分析中可以看出,获救与否与年龄呈现山峰的关系,故这种解释不太正常; 
       还有一个问题,我们仔细观察name数据,可以发现,名字中没有Mr,Mrs,Miss等,在结合父母孩子的数量,我们大致来猜测age缺失值,于是我们猜想可不可以利用其他的一些的特征来拟合age的缺失值。
    • Age属性不使用现在的拟合方式,而是根据名称中的『Mr』『Mrs』『Miss』等的平均值进行填充(缺失值的填充)。
    • Age不做成一个连续值属性,而是使用一个步长进行离散化,变成离散的类目feature(连续变量离散化)。
    • Pclass和Sex俩太重要了,我们试着用它们去组出一个组合属性来试试,这也是另外一种程度的细化(特征组合)。
    • 单加一个Child字段,Age<=12的,设为1,其余为0(你去看看数据,确实小盆友优先程度很高啊)(特征构造)
    • 如果名字里面有『Mrs』,而Parch>1的,我们猜测她可能是一个母亲,应该获救的概率也会提高,因此可以多加一个Mother字段,此种情况下设为1,其余情况下设为0(特征构造)
    • Name是一个我们一直没有触碰的属性,我们可以做一些简单的处理,比如说男性中带某些字眼的(‘Capt’, ‘Don’, ‘Major’, ‘Sir’)可以统一到一个Title,女性也一样。
    • Cabin再细化一些,对于有记录的Cabin属性,我们将其分为前面的字母部分(我猜是位置和船层之类的信息)和后面的数字部分(应该是房间号,有意思的事情是,如果你仔细看看原始数据,你会发现,这个值大的情况下,似乎获救的可能性高一些)。
    • 把堂兄弟/兄妹 和 Parch 还有自己 个数加在一起组一个Family_size字段(考虑到大家族可能对最后的结果有影响)
    # 可以组成一个大家族的特征
    df['family'] = df['Parch']+df['SibSp']+1
    df['family'].value_counts()

    Out[43]:

    1     790
    2     235
    3     159
    4      43
    6      25
    5      22
    7      16
    11     11
    8       8
    Name: family, dtype: int64
    #通过正则表达式来获取称谓
    import re
    def get_title(name):
        pre_name = re.search(r', ([A-Za-z]+)\.',name)
        if pre_name:
            return pre_name.group(1)
        else:
            return np.nan
    df['pre_name'] = df['Name'].apply(get_title)
    df.head()

    df.info()
    df[df['pre_name'].isnull()]

    # 通过查看数据,我们替换掉缺失值
    df['pre_name'].replace(np.nan,'Mrs',inplace = True)
    df.ix[759]
    df.info()
    
    df['pre_name'].value_counts()

    Out[48]:

    Mr          757
    Miss        260
    Mrs         198
    Master       61
    Dr            8
    Rev           8
    Col           4
    Ms            2
    Major         2
    Mlle          2
    Don           1
    Capt          1
    Dona          1
    Lady          1
    Mme           1
    Sir           1
    Jonkheer      1
    Name: pre_name, dtype: int64

    通过仔细的对比数据,Master这里对应的年龄基本在12岁以下,所以我们前面用所有人的均值来替代缺失值是有问题的

    df['pre_name'] = df['pre_name'].replace('Mlle', 'Miss')
    df['pre_name'] = df['pre_name'].replace('Ms', 'Miss')
    df['pre_name'] = df['pre_name'].replace('Mme', 'Mrs')
    df['pre_name'] = df['pre_name'].replace('Lady', 'Mrs')
    df['pre_name'] = df['pre_name'].replace('Sir', 'Mr')
    df['pre_name'] = df['pre_name'].replace(['Dr','Rev','Col','Major','Dona','Don','Capt','Jonkheer'], 'Rare')
    
    df.info()
    df.head()
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 1309 entries, 0 to 417
    Data columns (total 15 columns):
    Age            1046 non-null float64
    Cabin          295 non-null object
    Data_type      1309 non-null object
    Embarked       1307 non-null object
    Fare           1308 non-null float64
    Name           1309 non-null object
    Parch          1309 non-null int64
    PassengerId    1309 non-null int64
    Pclass         1309 non-null int64
    Sex            1309 non-null object
    SibSp          1309 non-null int64
    Survived       891 non-null float64
    Ticket         1309 non-null object
    family         1309 non-null int64
    pre_name       1309 non-null object
    dtypes: float64(3), int64(5), object(7)
    memory usage: 203.6+ KB

    对缺失值常用的处理方法有填充平均值,这里我们不用平均值来填充,利用已知数据来拟合缺失值的情况
    1 由于Cabin缺失值太多,我们直接舍弃这个特征
    2 对age我们利用随机森林来进行拟合。

    from sklearn.ensemble import RandomForestRegressor
    
    def fill_miss_age(data):
        age_df = data[['Age','Fare','Parch','SibSp','Pclass','pre_name']]
        # 先填充fare的缺失值,这个直接利用均值
        age_df = pd.get_dummies(age_df)
        age_df['Fare'] = age_df['Fare'].fillna(test_df['Fare'].mean())
        know_age_df = age_df[age_df['Age'].notnull()]
        unknow_age_df = age_df[age_df.Age.isnull()]
    
        know_y_age = know_age_df.ix[:,0]
        know_x_age = know_age_df.ix[:,1:]
        rfr = RandomForestRegressor(random_state=0, n_estimators=500, n_jobs=-1)
        rfr.fit(know_x_age, know_y_age)
        predictedAges = rfr.predict(unknow_age_df.ix[:,1:])
        data.loc[data.Age.isnull(),'Age']=predictedAges
        return data
    fill_df= fill_miss_age(df)
    fill_df.info()
    fill_df.head()

     

    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 1309 entries, 0 to 417
    Data columns (total 15 columns):
    Age            1309 non-null float64
    Cabin          295 non-null object
    Data_type      1309 non-null object
    Embarked       1307 non-null object
    Fare           1308 non-null float64
    Name           1309 non-null object
    Parch          1309 non-null int64
    PassengerId    1309 non-null int64
    Pclass         1309 non-null int64
    Sex            1309 non-null object
    SibSp          1309 non-null int64
    Survived       891 non-null float64
    Ticket         1309 non-null object
    family         1309 non-null int64
    pre_name       1309 non-null object
    dtypes: float64(3), int64(5), object(7)
    memory usage: 203.6+ KB
    

    #### 对pclass进行转换
    p_class = pd.get_dummies(fill_df.Pclass,prefix='Pclass_')
    p_class.head()
    
    #### 对性别进行转换
    Sex=pd.get_dummies(fill_df['Sex'],prefix='Sex')
    Sex.head()
    
    #### 对船票的价格进行处理,使用归一化的操作,减少异常值的干扰
    import sklearn.preprocessing as preprocessing
    scaler = preprocessing.StandardScaler()
    fill_df['Fare'] = fill_df['Fare'].fillna(test_df['Fare'].mean())
    fare_train = fill_df.loc[fill_df['Data_type']=='train','Fare'].reshape(-1,1)
    fare_test = fill_df.loc[fill_df['Data_type']=='test','Fare'].reshape(-1,1)
    s = scaler.fit(fare_train)
    Standard_train = s.transform(fare_train)
    s1 = scaler.fit(fare_test)
    Standard_test = s1.transform(fare_test)
    Standard_train_df = pd.DataFrame(Standard_train)
    Standard_test_df =pd.DataFrame(Standard_test) 
    fare_df = pd.concat([Standard_train_df,Standard_test_df])
    fare_df.columns=['farescal',]
    all_df = pd.concat([fill_df,fare_df],axis = 1)
    all_df.head()

    ### 对age进行离散化处理
    #### 1 age<12 ;
    #### 2 age=[12,20];
    #### 3 age=[20,32];
    #### 4 age=[32,45];
    #### 5 age=[45,60];
    #### 6 age>60 
    
    bins = [0,12,20,32,45,60,100]
    all_df['Age'] = pd.cut(all_df['Age'],bins=bins)
    all_df.head()

    age_dummies= pd.get_dummies(all_df.Age,prefix = 'age_')
    age_dummies.head()

    #### 对头衔进行处理
    pre_name = pd.get_dummies(all_df.pre_name)
    pre_name.head()
    
    #### 判断是否是一个母亲
    all_df['is_mother']=0
    all_df.loc[(all_df['Sex']=='female') & (all_df['Parch']>0) &(all_df['pre_name']=='Mrs'),'is_mother']=1
    all_df.head()
    
    #### sex和plcass的特征值组合
    all_df['plcass_sex'] =all_df['Sex']+'_'+all_df['Pclass'].astype(np.str)
    plcass_sex = pd.get_dummies(all_df['plcass_sex'])
    plcass_sex.head()
    

    所有变量合并

    alldf=pd.concat([all_df,pre_name,age_dummies,Sex,p_class,plcass_sex],axis = 1)
    alldf.head()

    train_feature_x = alldf.loc[alldf['Data_type']=='train',['SibSp','Parch','farescal','family', 'is_mother','Sex_female','Sex_male','age__(0, 12]','age__(12, 20]','age__(20, 32]','age__(32, 45]','age__(45, 60]','age__(60, 100]','Master','Miss','Mr','Mrs','Rare','Pclass__1','Pclass__2','Pclass__3']]
    train_feature_y = alldf.loc[alldf['Data_type']=='train','Survived']
    test_feature_x = alldf.loc[alldf['Data_type']=='test',['SibSp','Parch','farescal','family','is_mother','Sex_female','Sex_male','age__(0, 12]','age__(12, 20]','age__(20, 32]','age__(32, 45]','age__(45, 60]','age__(60, 100]','Master','Miss','Mr','Mrs','Rare','Pclass__1','Pclass__2','Pclass__3']]
    train_feature_x.head()

    拆分训练集和验证集

    x_train,x_test,y_train,y_test = model_selection.train_test_split(train_feature_x,train_feature_y,test_size=0.3,random_state=33)
    #### 模型训练
    names = ['LogisticRegression','LinearSVC','KNeighborsClassifier','RandomForestClassifier','DecisionTreeClassifier']
    clfs =[LogisticRegression(),LinearSVC(),KNeighborsClassifier(n_neighbors=3),RandomForestClassifier(),DecisionTreeClassifier()]
    for name,clf in zip(names,clfs):
        clf.fit(x_train,y_train)
        print(clf)
        print("train_score:",clf.score(x_train,y_train))
        y_pre = clf.predict(x_test)
        test_score = metrics.accuracy_score(y_pre,y_test)
        print("test_score:",test_score)
        print('\n')
    LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
              intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
              penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
              verbose=0, warm_start=False)
    train_score: 0.817014446228
    test_score: 0.850746268657
    
    
    LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
         intercept_scaling=1, loss='squared_hinge', max_iter=1000,
         multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
         verbose=0)
    train_score: 0.817014446228
    test_score: 0.85447761194
    
    
    KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
               metric_params=None, n_jobs=1, n_neighbors=3, p=2,
               weights='uniform')
    train_score: 0.866773675762
    test_score: 0.817164179104
    
    
    RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                max_depth=None, max_features='auto', max_leaf_nodes=None,
                min_impurity_decrease=0.0, min_impurity_split=None,
                min_samples_leaf=1, min_samples_split=2,
                min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
                oob_score=False, random_state=None, verbose=0,
                warm_start=False)
    train_score: 0.926163723917
    test_score: 0.809701492537
    
    
    DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
                max_features=None, max_leaf_nodes=None,
                min_impurity_decrease=0.0, min_impurity_split=None,
                min_samples_leaf=1, min_samples_split=2,
                min_weight_fraction_leaf=0.0, presort=False, random_state=None,
                splitter='best')
    train_score: 0.939004815409
    test_score: 0.820895522388
    

    从这次的模型可以看出,训练集和测试集的准确率都有了提高,这印证了工业界的一个观点,特征工程的好坏决定的算法的上限,而模型的好坏只是无限逼近这个上限

    接下来,我们尝试着做下模型的融合,这个要特别注意,模型的融合很容易造成过拟合

    from sklearn.ensemble import VotingClassifier
    %run 4.特征工程--准备一个更好的数据集.ipynb
    
    lr = LogisticRegression()
    lsvc=LinearSVC()
    knn=KNeighborsClassifier(n_neighbors=3)
    random_forest=RandomForestClassifier()
    dtree=DecisionTreeClassifier()
    
    votingclf = VotingClassifier(estimators=[('lr',lr),('lsvc',lsvc),('knn',knn),('random_forest',random_forest),('dtree',dtree)],voting='hard')
    #训练集投票后的结果
    votingclf.fit(x_train,y_train)
    print("训练融合得分:",votingclf.score(x_train,y_train))
    #测试集投票后的结果
    y_predict = votingclf.predict(x_test)
    print("验证融合得分:",metrics.accuracy_score(y_predict,y_test))

    至此,整个项目算是结束了,就差拿模型去测试集上去做测试了

    http://sklearn.apachecn.org/cn/0.19.0/modules/generated/sklearn.ensemble.VotingClassifier.html#sklearn.ensemble.VotingClassifier(模型融合的官网) 

    展开全文
  • 作者:[法] 奥雷利安·杰龙(Aurélien Géron) 著,宋能辉,李娴 译 出版社:机械工业出版社 品牌:机械工业出版社 出版时间:2020-10-01 机器学习实战:基于Scikit-Learn、Keras和TensorFlow

    作者:[法] 奥雷利安·杰龙(Aurélien Géron) 著,宋能辉,李娴 译
    出版社:机械工业出版社
    品牌:机工出版
    出版时间:2020-10-01
    机器学习实战:基于Scikit-Learn、Keras和TensorFlow

    展开全文
  •   趁着还没工作,看看有意思的东西,这片文章是解决《GO语言机器学习实战》遇到的一些问题而写的,该书的译版是这样的 这本书大概就讲了一些应用,当然也包括最经典的MNIST手写数字识别。不过我看了一下某宝和某东...

    开新坑

      趁着还没工作,看看有意思的东西,这片文章是解决《GO语言机器学习实战》遇到的一些问题而写的,该书的译版是这样的在这里插入图片描述
    这本书大概就讲了一些应用,当然也包括最经典的MNIST手写数字识别。不过我看了一下某宝和某东,发现这本书销量不高,有一说一,小白还是使用主流的python来学习机器学习比较好,毕竟要掌握的知识和遇到的问题太多了。看这书就相当于涨涨见识吧。
      在某宝上看到该书的评论,有一个说作者给的代码都是错的,今天试着运行第二章的“线性回归——房价预测”的代码,发现IDE确实报了不少错,而该书毕竟是比较冷门的,也没有看到有什么文章来解决这些问题,幸运的是错误并不多,目前我只是把它修复并完整跑了出来,并没有研究代码是怎么写的。后续还需要看看代码逻辑,接下来还是讲讲代码的修复过程吧。

    本书资源

      中文译版并没有给出该书代码的资源下载地址,在机械工业出版社我也没发现资源,幸好知道该书的英文名,还真让我搜到了。巧的是第二章给出的数据集的地址也是错的,不知道是不是译本的问题。顺便给出遇到问题的第三方库gonum的地址吧。

    1. 该书的所有代码
    2. 第二章的数据集
    3. gonum

    问题以及解决

    导包

      这没什么好说的,直接go mod tidy,我最后得到的go.mod文件如下

    module GOML
    
    go 1.15
    
    require (
    	github.com/pkg/errors v0.9.1
    	github.com/sajari/regression v1.0.1
    	golang.org/x/exp v0.0.0-20210511203234-0325d671925d
    	gonum.org/v1/gonum v0.9.1
    	gonum.org/v1/plot v0.9.0
    	gorgonia.org/tensor v0.9.20
    	gorgonia.org/vecf64 v0.9.0
    )
    

    代码报错

      导完包后,右边栏就是一大段报错了,不过棘手的也就是一处
    在这里插入图片描述
      最多的报错就是跟plot相关的代码了,整个代码的报错地方有

    249行、277行、310行的
    p, err := plot.New()
    与第325行的
    l, err := plot.NewLegend()
    以及第355行的
    l.Font.Size = 5
    比较棘手的第481行的
    corr := stat.CorrelationMatrix(nil, m64, nil)
    与第493行的
    if c := corr.At(i, j); math.Abs(c) >= 0.5 && h1 != h2
    

    解决方案

      对于与plot相关的报错,点进plot.New()代码里面发现其代码是这样的

    // New returns a new plot with some reasonable default settings.
    func New() *Plot {
    	hdlr := DefaultTextHandler
    	p := &Plot{
    		BackgroundColor: color.White,
    		X:               makeAxis(horizontal),
    		Y:               makeAxis(vertical),
    		Legend:          newLegend(hdlr),
    		TextHandler:     hdlr,
    	}
    	p.Title.TextStyle = text.Style{
    		Color:   color.Black,
    		Font:    font.From(DefaultFont, 12),
    		XAlign:  draw.XCenter,
    		YAlign:  draw.YTop,
    		Handler: hdlr,
    	}
    	return p
    }
    

      因为该函数其实只返回*Plot,并没返回error,所以没啥好说的,将代码中报错地方的err删掉即可,对应的改变为

    原版
    p, err := plot.New()
    if err != nil {
    	return nil, err
    }
    改动后的版本
    p := plot.New()
    

      对于第310行的错误,其改动方式为

    原版
    if p, err = plot.New(); err != nil {
    	return
    }
    改版
    p = plot.New() // 因为这里需要返回它,所以要创建一个
    

      第325行的plot.NewLegend()同理,该函数并没有返回error

    原版
    // add legend
    l, err := plot.NewLegend()
    if err != nil {
    	return p, err
    }
    改版
    // add legend
    l := plot.NewLegend()
    //if err != nil {
    //	return p, err
    //}
    

      第355行,直接注释掉就行,这个l应该是绘图的图例属性,Font这个属性就是字体大小,但是因为时间的关系,改包已经迭代了不少版本,legend这个结构体的直接字段并没有Font了,所以暂时可将该代码注释掉。也可根据更改后的结构改成如下代码

    原版
    l.Font.Size = 5
    改版
    1. 直接注释
    //l.Font.Size = 5
    2.根据新字段添加
    l.TextStyle.Font.Size = 5
    

      legend的字段如下

    type Legend struct {
    	// TextStyle is the style given to the legend
    	// entry texts.
    	TextStyle text.Style
    
    	// Padding is the amount of padding to add
    	// between each entry in the legend.  If Padding
    	// is zero then entries are spaced based on the
    	// font size.
    	Padding vg.Length
    
    	// Top and Left specify the location of the legend.
    	// If Top is true the legend is located along the top
    	// edge of the plot, otherwise it is located along
    	// the bottom edge.  If Left is true then the legend
    	// is located along the left edge of the plot, and the
    	// text is positioned after the icons, otherwise it is
    	// located along the right edge and the text is
    	// positioned before the icons.
    	Top, Left bool
    
    	// XOffs and YOffs are added to the legend's
    	// final position.
    	XOffs, YOffs vg.Length
    
    	// YPosition specifies the vertical position of a legend entry.
    	// Valid values are [-1,+1], with +1 being the top of the
    	// entry vertical space, and -1 the bottom.
    	YPosition float64
    
    	// ThumbnailWidth is the width of legend thumbnails.
    	ThumbnailWidth vg.Length
    
    	// entries are all of the legendEntries described
    	// by this legend.
    	entries []legendEntry
    }
    

      然后重头戏来了,第481行的代码错误,给的代码是这样的

    corr := stat.CorrelationMatrix(nil, m64, nil)
    

      但是点进stat包查阅CorrelationMatrix函数的代码是这样的

    // CorrelationMatrix returns the correlation matrix calculated from a matrix
    // of data, x, using a two-pass algorithm. The result is stored in dst.
    //
    // If weights is not nil the weighted correlation of x is calculated. weights
    // must have length equal to the number of rows in input data matrix and
    // must not contain negative elements.
    // The dst matrix must either be empty or have the same number of
    // columns as the input data matrix.
    func CorrelationMatrix(dst *mat.SymDense, x mat.Matrix, weights []float64) {
    	// This will panic if the sizes don't match, or if weights is the wrong size.
    	CovarianceMatrix(dst, x, weights)
    	covToCorr(dst)
    }
    

      emmm,并没有返回任何东西啊,虽然注释说将所得结果存在了dst里面,但是作者给的代码并不符合该函数的要求。考虑到距离作者给出改代码的时间已经3年左右了,可能是gonum包的版本问题,所以去github上找,还真让我找到了一个gonum,它的目录是这样的,红圈哪个其实就是我们导入的包gonum.org/v1/gonum
    在这里插入图片描述
      而在该图片的同级目录下有一个stat包,而该包的statmat.go中的CorrelationMatrix函数是这样的

    // CorrelationMatrix returns the correlation matrix calculated from a matrix
    // of data, x, using a two-pass algorithm.
    //
    // If weights is not nil the weighted correlation of x is calculated. weights
    // must have length equal to the number of rows in input data matrix and
    // must not contain negative elements.
    // If corr is not nil it must either be zero-sized or have the same number of
    // columns as the input data matrix. corr will be used as the destination for
    // the correlation data. If corr is nil, a new mat64.SymDense is allocated for
    // the destination.
    func CorrelationMatrix(corr *mat64.SymDense, x mat64.Matrix, weights []float64) *mat64.SymDense {
    	// This will panic if the sizes don't match, or if weights is the wrong size.
    	corr = CovarianceMatrix(corr, x, weights)
    	covToCorr(corr)
    	return corr
    }
    

      嗯,感觉方向对了,毕竟有了这个corr,但是改包与导入的gonum是属于同一级的,而使用的是gonum.org/v1/gonum/stat,就很麻烦,最后我将同级的stat对gonum包下的stat进行置换,发现解决不了问题。毕竟又多了个mat64这种东西,所以最后还是根据最新版的gonum进行改动。
      参考CovarianceMatrix函数的注释与stat包下的statmat_test.go的TestCorrelationMatrix函数第170行代码

    var corr mat.SymDense
    CorrelationMatrix(&corr, test.data, test.weights)
    

      该进的地方是这样的

    // 481行原来是这样的
    corr := stat.CorrelationMatrix(nil, m64, nil)
    hm, err := plotHeatMap(corr, newHdr)
    mHandleErr(err)
    // 改动后是这样的
    var corr mat.SymDense
    stat.CorrelationMatrix(&corr, m64, nil)
    hm, err := plotHeatMap(corr, newHdr)
    mHandleErr(err)
    

      按照上述方式改动代码后,会在hm, err := plotHeatMap(corr, newHdr)报错,查看代码发现

    // plotHeatMap这个函数是main函数里作者写的,需要的是mat.Matrix
    func plotHeatMap(corr mat.Matrix, labels []string) (p *plot.Plot, err error) 
    // 但是经过改动后传给plotHeatMap函数的corr是mat.SymDense
    所以需要将该函数改为
    func plotHeatMap(corr mat.SymDense, labels []string) (p *plot.Plot, err error)
    

      但是改了之后发现plotHeatMap函数里面的第二行代码又报错了,

    // 报错代码
    m := heatmap{corr}
    
    // 原因
    // 原因是因为在main.go中定义的heatmap结构体中的x字段为mat.Matrix
    type heatmap struct {
    	x mat.Matrix
    }
    // 改错
    // 所以将heatmap字段改成这样就行了
    type heatmap struct {
    	x mat.SymDense
    }
    

      那么为什么修改成这样就行了呢,看看mat包下的symmetric.go就行了
    在这里插入图片描述
      如图所示,这个结构体是实现了接口的,而肯定的是该结构体实现了Matrix接口,Matrix接口如下

    // Matrix is the basic matrix interface type.
    type Matrix interface {
    	// Dims returns the dimensions of a Matrix.
    	Dims() (r, c int)
    
    	// At returns the value of a matrix element at row i, column j.
    	// It will panic if i or j are out of bounds for the matrix.
    	At(i, j int) float64
    
    	// T returns the transpose of the Matrix. Whether T returns a copy of the
    	// underlying data is implementation dependent.
    	// This method may be implemented using the Transpose type, which
    	// provides an implicit matrix transpose.
    	T() Matrix
    }
    

      对应的SymDense结构体实现的Matrix接口方法在mat包中的symmetric.go中有Dims()和T()

    在这里插入图片描述
      在mat包中的index_no_bound_checks.go文件实现了At()
    在这里插入图片描述
      所以第二章的代码错误就改完了。不过main.go文件在第一行将绘图的函数exploration()注释了,可根据需要将其运行

    结果

    文件结构

      文件放置关系是这样的
    在这里插入图片描述
      代码跑出来会产生对应的图,不会直接显示,而是将其保存,结构是这样的
    在这里插入图片描述

    图片结果

    CEF.png在这里插入图片描述
    hist.png
    在这里插入图片描述
    hist2.png
    在这里插入图片描述
    heatmap.png
    在这里插入图片描述

    控制台输出

      奇怪的是结果与书上一模一样,难道参数固定?毕竟我也没仔细研究代码
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 机器学习部分课后习题答案,米切尔版的课后答案,卡内基梅隆大学,Tom.M.Mitchell
  • 机器学习实战之路 —— 1 线性回归一1. 线性回归2. 标准线性回归2.1 方程组求解2.2 矩阵求解3. 实战4. 参考学习的书目及论文 近期自己准备将之前在机器学习方面做的一些学习及研究工作,重新稍加整理成稿发出来,权...

    近期自己准备将之前在机器学习方面做的一些学习及研究工作,重新稍加整理成稿发出来,权当记录分享。俗话说,好记性不如烂笔头,有时候自己理解是一个层次,而写出来给别人看,往往需要站在受众的角度去思考,进而希望更好的传达自己的观点和想法,所以在文章构思及落笔成文时,已经加深了自己对原本问题和相关知识的理解,这是比仅仅自己理解更深入的一个层次。回顾自己求学及工作中整理撰写各类论文及报告时,莫不如此。分享不仅是对自己过往学习的一个回顾,一定程度上也是驱动进一步学习的动力。

    1. 线性回归

    回归问题和分类问题的区别仅仅在于设定的目标值得类型不同。分类设定的目标值是离散的,意义是“类别”;而回归设定的目标值是连续的,意义是某种“数值”。由于仅仅是目标值不同,所以对于大部门的机器学习模型而言,一般都有对应的“分类版”模型实现和“回归版”模型实现。相对应的分类模型和回归模型在实现思路上非常相近,一般而言,两者的主要区别在于:
    *目标数值的类型不同(离散值 vs 连续值)
    *损失函数设计不同
    *评估指标选择不同
    ——《机器学习之路》 P 61 P_{61} P61

    线性模型形式简单、易于建模,但却蕴涵着机器学习中一些重要的基本思想。许多功能更为强大的非线性模型 (nonlinear model)可在线性模型的基础上通过引入层级结构或高维映射而得。此外,由于 ω 直观表达了各属性在预测中的重要性,因此线性模型有很好的可解释性 (comprehensibility)。
    ——《机器学习-周志华》 P 53 P_{53} P53

    优点:结果易于理解,计算上不复杂。
    缺点:对非线性的数据拟合不好。
    适用数据类型:数值型和标称型数据。
    ——《机器学习实战》 P 136 P_{136} P136

    回归的一般方法:

    1. 收集数据:采用任意方法收集数据。
    2. 准备数据:回归需要数值型数据,标称型数据将被转成二值型数据。
    3. 分析数据:绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后, 可以将新拟合线绘在图上作为对比。
    4. 训练算法:找到回归系数。
    5. 测试算法:使用 R 2 R^2 R2或者预测值和数据的拟合度,来分析模型的效果。
    6. 使用算法:使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。
      ——《机器学习实战》 P 137 P_{137} P137

    2. 标准线性回归

    2.1 方程组求解

    在此首先将以线性回归为例,介绍回归算法和模型。回归分析是迄今为止数值型数据建模最常用的方法,可以适用几乎所有的数据,且提供了变量与结果之间强度与大小的估计。在线性回归的学习过程中,在此也将会展开论述其中的推导过程。

    对于给定数据集 D = { ( x 1 , y 1 ) , ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . . . . , ( x m , y m ) } D=\{ (x_1,y_1),(x_1,y_1),(x_2,y_2),......,(x_m,y_m)\} D={(x1,y1),(x1,y1),(x2,y2),......,(xm,ym)},其中 x i = ( x i 1 , x i 1 , . . . . . . , x i d ) x_i=(x_i1,x_i1,......,x_id) xi=(xi1,xi1,......,xid), y i ∈ R y_i\in R yiR,线性回归(linear regression)试图学得一个线性模型 f ( x i ) = ω ∗ x i + b f(x_i)=ω* x_i+b f(xi)=ωxi+b,以尽可能准确地预测实值输出标记 f ( x i ) ≈ y i f(x_i)\approx y_i f(xi)yi

    回归任务中常使用均方误差来衡量 f(x) 与 y 之间的差别。使均方误差最小化得到的 ω, b 即我们所求。基于均方误差来进行模型求解的方法称为最小二乘法:

    L ( ω , b ) = ∑ i = 1 m ( y i − f ( x i ) ) 2 = ∑ i = 1 m ( y i − ( ω ∗ x i + b ) ) 2 ( 2.1 ) \begin{aligned} L(ω,b)&=\sum_{i=1}^{m}(y_i-f(x_i))^2 \\ &=\sum_{i=1}^{m}(y_i-(ω* x_i+b))^2 \qquad (2.1) \end{aligned} L(ω,b)=i=1m(yif(xi))2=i=1m(yi(ωxi+b))2(2.1)
    L(ω,b)是关于ω和b的凸函数,当它关于ω和b导数均为0时,可得到ω和b的最优解。

    求解 b,将L(ω,b)对b求偏导令其等于零:
    ∂ L ( ω , b ) ∂ b = 2 ∗ ( ∑ i = 1 m ( y i − ( ω ∗ x i + b ) ) ) ∗ ( − 1 ) = 0 ∑ i = 1 m y i = ∑ i = 1 m ( ω ∗ x i + b ) ∑ i = 1 m y i = ω ∑ i = 1 m x i + m ∗ b 1 m ∑ i = 1 m y i = 1 m ∗ ω ∑ i = 1 m x i + b y i ‾ = ω ∗ x i ‾ + b b = y i ‾ − ω ∗ x i ‾ \begin{aligned} \frac{\partial L(ω,b)}{\partial b} =2*(\sum_{i=1}^{m}(y_i-(ω* x_i+b)))* (-1)&=0\\ \sum_{i=1}^{m}y_i &=\sum_{i=1}^{m}(ω* x_i+b)\\ \sum_{i=1}^{m}y_i &=ω\sum_{i=1}^{m}x_i+m* b\\ \frac{1}{m}\sum_{i=1}^{m}y_i &=\frac{1}{m}* ω\sum_{i=1}^{m}x_i+b\\ \overline{y_i} &=ω*\overline{x_i}+b \\ b &=\overline{y_i} - ω*\overline{x_i} \end{aligned} bL(ω,b)=2(i=1m(yi(ωxi+b)))(1)i=1myii=1myim1i=1myiyib=0=i=1m(ωxi+b)=ωi=1mxi+mb=m1ωi=1mxi+b=ωxi+b=yiωxi

    b的表达式为:
    b = y i ‾ − ω ∗ x i ‾ ( 2.2 ) b=\overline{y_i} - ω*\overline{x_i} \qquad (2.2) b=yiωxi(2.2)
    其中: x ‾ = 1 m ∗ ∑ i = 1 m x i \overline{x}=\frac{1}{m}* \sum_{i=1}^{m}x_i x=m1i=1mxi y ‾ = 1 m ∗ ∑ i = 1 m y i \overline{y}=\frac{1}{m}* \sum_{i=1}^{m}y_i y=m1i=1myi
    求解ω,将L(ω,b)对ω求导令其等于零:
    ∂ L ( ω , b ) ∂ ω = 2 ∗ ( ∑ i = 1 m ( y i − ( ω ∗ x i + b ) ) ) ∗ ( − x i ) = 0 ( ∑ i = 1 m ( y i ∗ x i ) ) = ω ∑ i = 1 m x i 2 + ∑ i = 1 m b ∗ x i \begin{aligned} \frac{\partial L(ω,b)}{\partial ω} =2*(\sum_{i=1}^{m}(y_i-(ω* x_i+b)))* (-x_i) &= 0\\ (\sum_{i=1}^{m}(y_i* x_i)) &= ω\sum_{i=1}^{m}x_i^2+\sum_{i=1}^{m}b* x_i\\ \end{aligned} ωL(ω,b)=2(i=1m(yi(ωxi+b)))(xi)(i=1m(yixi))=0=ωi=1mxi2+i=1mbxi
    b = y i ‾ − ω ∗ x i ‾ b=\overline{y_i} - ω*\overline{x_i} b=yiωxi带入上式:
    ∑ i = 1 m y i ∗ x i = ω ∑ i = 1 m x i 2 + ∑ i = 1 m ( y i ‾ − ω ∗ x i ‾ ) ∗ x i ∑ i = 1 m y i ∗ x i = ω ∑ i = 1 m x i 2 + y i ‾ ∑ i = 1 m x i − ω ∗ x i ‾ ∑ i = 1 m x i ω ∗ ( ∑ i = 1 m x i 2 − x i ‾ ∑ i = 1 m x i ) = ∑ i = 1 m y i ∗ x i − y i ‾ ∑ i = 1 m x i ω = ∑ i = 1 m y i ∗ x i − y i ‾ ∑ i = 1 m x i ∑ i = 1 m x i 2 − x i ‾ ∑ i = 1 m x i ( 2.3 ) \begin{aligned} \sum_{i=1}^{m}y_i* x_i &= ω\sum_{i=1}^{m}x_i^2+\sum_{i=1}^{m}(\overline{y_i} - ω*\overline{x_i})* x_i\\ \sum_{i=1}^{m}y_i* x_i &= ω\sum_{i=1}^{m}x_i^2+\overline{y_i}\sum_{i=1}^{m} x_i - ω*\overline{x_i}\sum_{i=1}^{m} x_i\\ ω* (\sum_{i=1}^{m}x_i^2-\overline{x_i}\sum_{i=1}^{m} x_i )&=\sum_{i=1}^{m}y_i* x_i -\overline{y_i}\sum_{i=1}^{m}x_i \\ ω &=\frac{ \sum_{i=1}^{m}y_i* x_i -\overline{y_i}\sum_{i=1}^{m}x_i }{ \sum_{i=1}^{m}x_i^2-\overline{x_i}\sum_{i=1}^{m} x_i } \qquad (2.3) \end{aligned} i=1myixii=1myixiω(i=1mxi2xii=1mxi)ω=ωi=1mxi2+i=1m(yiωxi)xi=ωi=1mxi2+yii=1mxiωxii=1mxi=i=1myixiyii=1mxi=i=1mxi2xii=1mxii=1myixiyii=1mxi(2.3)
    上式(2.3)中:
    y i ‾ ∑ i = 1 m x i = 1 m ∑ i = 1 m y i ∑ i = 1 m x i = 1 m ∑ i = 1 m x i ∑ i = 1 m y i = x i ‾ ∑ i = 1 m y i y i ‾ ∑ i = 1 m x i = x i ‾ ∑ i = 1 m y i ( 2.4 ) \begin{aligned} \overline{y_i}\sum_{i=1}^{m}x_i &= \frac{1}{m} \sum_{i=1}^{m}y_i\sum_{i=1}^{m}x_i \\ &= \frac{1}{m} \sum_{i=1}^{m}x_i \sum_{i=1}^{m}y_i\\ &= \overline{x_i}\sum_{i=1}^{m}y_i \\ \overline{y_i}\sum_{i=1}^{m}x_i =\overline{x_i}\sum_{i=1}^{m}y_i \qquad (2.4) \end{aligned} yii=1mxiyii=1mxi=xii=1myi(2.4)=m1i=1myii=1mxi=m1i=1mxii=1myi=xii=1myi
    此外:
    y i ‾ ∑ i = 1 m x i = m ∗ 1 m ∗ y i ‾ ∑ i = 1 m x i = m ∗ y i ‾ ∗ x i ‾ = ∑ i = 1 m y i ‾ ∗ x i ‾ y i ‾ ∑ i = 1 m x i = ∑ i = 1 m y i ‾ ∗ x i ‾ ( 2.5 ) \begin{aligned} \overline{y_i}\sum_{i=1}^{m}x_i &= m*\frac{1}{m} * \overline{y_i}\sum_{i=1}^{m}x_i \\ &= m* \overline{y_i}* \overline{x_i} \\ &= \sum_{i=1}^{m}\overline{y_i}* \overline{x_i} \\ \overline{y_i}\sum_{i=1}^{m}x_i =\sum_{i=1}^{m}\overline{y_i}* \overline{x_i} \qquad (2.5) \end{aligned} yii=1mxiyii=1mxi=i=1myixi(2.5)=mm1yii=1mxi=myixi=i=1myixi
    联立(2.4)和(2.5),可得式(2.6)及推广(2.7):
    y i ‾ ∑ i = 1 m x i = x i ‾ ∑ i = 1 m y i = ∑ i = 1 m y i ‾ ∗ x i ‾ ( 2.6 ) x i ‾ ∑ i = 1 m x i = x i ‾ ∑ i = 1 m x i = ∑ i = 1 m x i ‾ 2 ( 2.7 ) \begin{aligned} \overline{y_i}\sum_{i=1}^{m}x_i =\overline{x_i}\sum_{i=1}^{m}y_i = \sum_{i=1}^{m}\overline{y_i}* \overline{x_i} \qquad (2.6) \\ \overline{x_i}\sum_{i=1}^{m}x_i =\overline{x_i}\sum_{i=1}^{m}x_i = \sum_{i=1}^{m}\overline{x_i}^2 \qquad (2.7) \\ \end{aligned} yii=1mxi=xii=1myi=i=1myixi(2.6)xii=1mxi=xii=1mxi=i=1mxi2(2.7)
    同样推导可得:
    x i ‾ ∑ i = 1 m x i = 1 m ∑ i = 1 m x i ∑ i = 1 m x i = 1 m ( ∑ i = 1 m x i ) 2 x i ‾ ∑ i = 1 m x i = 1 m ( ∑ i = 1 m x i ) 2 ( 2.8 ) \begin{aligned} \overline{x_i}\sum_{i=1}^{m}x_i &= \frac{1}{m} \sum_{i=1}^{m}x_i\sum_{i=1}^{m}x_i \\ &= \frac{1}{m} (\sum_{i=1}^{m}x_i )^2\\ \overline{x_i}\sum_{i=1}^{m}x_i = \frac{1}{m} (\sum_{i=1}^{m}x_i )^2 \qquad (2.8) \end{aligned} xii=1mxixii=1mxi=m1(i=1mxi)2(2.8)=m1i=1mxii=1mxi=m1(i=1mxi)2
    将式(2.5) y i ‾ ∑ i = 1 m x i = x i ‾ ∑ i = 1 m y i \overline{y_i}\sum_{i=1}^{m}x_i =\overline{x_i}\sum_{i=1}^{m}y_i yii=1mxi=xii=1myi和式(2.8) x i ‾ ∑ i = 1 m x i = 1 m ( ∑ i = 1 m x i ) 2 \overline{x_i}\sum_{i=1}^{m}x_i = \frac{1}{m} (\sum_{i=1}^{m}x_i )^2 xii=1mxi=m1(i=1mxi)2带入式(2.3)即可得式(2.9):
    ω = ∑ i = 1 m y i ∗ x i − y i ‾ ∑ i = 1 m x i ∑ i = 1 m x i 2 − x i ‾ ∑ i = 1 m x i = ∑ i = 1 m y i ∗ x i − x i ‾ ∑ i = 1 m y i ∑ i = 1 m x i 2 − 1 m ( ∑ i = 1 m x i ) 2 = ∑ i = 1 m y i ∗ ( x i − x i ‾ ) ∑ i = 1 m x i 2 − 1 m ( ∑ i = 1 m x i ) 2 ( 2.9 ) \begin{aligned} ω &=\frac{ \sum_{i=1}^{m}y_i* x_i -\overline{y_i}\sum_{i=1}^{m}x_i }{ \sum_{i=1}^{m}x_i^2-\overline{x_i}\sum_{i=1}^{m} x_i } \\ &=\frac{ \sum_{i=1}^{m}y_i* x_i -\overline{x_i}\sum_{i=1}^{m}y_i }{ \sum_{i=1}^{m}x_i^2- \frac{1}{m} (\sum_{i=1}^{m}x_i )^2 } \\ &=\frac{ \sum_{i=1}^{m}y_i*( x_i -\overline{x_i}) }{ \sum_{i=1}^{m}x_i^2- \frac{1}{m} (\sum_{i=1}^{m}x_i )^2 } \qquad (2.9) \end{aligned} ω=i=1mxi2xii=1mxii=1myixiyii=1mxi=i=1mxi2m1(i=1mxi)2i=1myixixii=1myi=i=1mxi2m1(i=1mxi)2i=1myi(xixi)(2.9)
    联立ω和b表达式(2.9),(2.2),即可得ω,b的第一种表达形式 (2.10):
    ω = ∑ i = 1 m y i ∗ ( x i − x i ‾ ) ∑ i = 1 m x i 2 − 1 m ( ∑ i = 1 m x i ) 2 b = y i ‾ − ω ∗ x i ‾ ( 2.10 ) \begin{aligned} ω &=\frac{ \sum_{i=1}^{m}y_i*( x_i -\overline{x_i}) }{ \sum_{i=1}^{m}x_i^2- \frac{1}{m} (\sum_{i=1}^{m}x_i )^2 } \qquad b=\overline{y_i} - ω*\overline{x_i} \qquad (2.10) \end{aligned} ω=i=1mxi2m1(i=1mxi)2i=1myi(xixi)b=yiωxi(2.10)
    x ‾ = 1 m ∗ ∑ i = 1 m x i \overline{x}=\frac{1}{m}* \sum_{i=1}^{m}x_i x=m1i=1mxi y ‾ = 1 m ∗ ∑ i = 1 m y i \overline{y}=\frac{1}{m}* \sum_{i=1}^{m}y_i y=m1i=1myi带入式(2.10),整理即可得ω,b的第二种表达形式(2.11):
    ω = m ∗ ∑ i = 1 m y i ∗ x i − ∑ i = 1 m y i ∑ i = 1 m x i m ∗ ∑ i = 1 m x i 2 − ( ∑ i = 1 m x i ) 2 b = ∑ i = 1 m x i 2 ∑ i = 1 m y i − ∑ i = 1 m x i ∑ i = 1 m x i ∗ y i m ∗ ∑ i = 1 m x i 2 − ( ∑ i = 1 m x i ) 2 ( 2.11 ) \begin{aligned} ω =\frac{ m*\sum_{i=1}^{m}y_i* x_i - \sum_{i=1}^{m}y_i \sum_{i=1}^{m}x_i }{ m*\sum_{i=1}^{m}x_i^2-(\sum_{i=1}^{m}x_i )^2 } \qquad b=\frac{ \sum_{i=1}^{m}x_i^2 \sum_{i=1}^{m}y_i - \sum_{i=1}^{m}x_i \sum_{i=1}^{m}x_i* y_i }{ m*\sum_{i=1}^{m}x_i^2-(\sum_{i=1}^{m}x_i )^2 } \qquad (2.11) \end{aligned} ω=mi=1mxi2(i=1mxi)2mi=1myixii=1myii=1mxib=mi=1mxi2(i=1mxi)2i=1mxi2i=1myii=1mxii=1mxiyi(2.11)
    将式(2.6) 和式(2.7)带入式(2.9)即可得式(2.12):
    ω = ∑ i = 1 m y i ∗ x i − y i ‾ ∑ i = 1 m x i ∑ i = 1 m x i 2 − x i ‾ ∑ i = 1 m x i = ∑ i = 1 m y i ∗ x i − y i ‾ ∑ i = 1 m x i − x i ‾ ∑ i = 1 m y i + ∑ i = 1 m y i ‾ ∗ x i ‾ ∑ i = 1 m x i 2 − x i ‾ ∑ i = 1 m x i − x i ‾ ∑ i = 1 m x i + ∑ i = 1 m x i ‾ 2 = ∑ i = 1 m ( x i − x i ‾ ) ( y i − y i ‾ ) ∑ i = 1 m ( x i − x i ‾ ) 2 = c o v ( x , y ) v a r ( x ) ( 2.12 ) \begin{aligned} ω &=\frac{ \sum_{i=1}^{m}y_i* x_i -\overline{y_i}\sum_{i=1}^{m}x_i }{ \sum_{i=1}^{m}x_i^2-\overline{x_i}\sum_{i=1}^{m} x_i } \\ &=\frac{ \sum_{i=1}^{m}y_i* x_i -\overline{y_i}\sum_{i=1}^{m}x_i -\overline{x_i}\sum_{i=1}^{m}y_i + \sum_{i=1}^{m}\overline{y_i}* \overline{x_i} }{ \sum_{i=1}^{m}x_i^2-\overline{x_i}\sum_{i=1}^{m} x_i -\overline{x_i}\sum_{i=1}^{m}x_i + \sum_{i=1}^{m}\overline{x_i}^2 } \\ &=\frac{ \sum_{i=1}^{m}( x_i -\overline{x_i})( y_i - \overline{y_i}) }{ \sum_{i=1}^{m} (x_i- \overline{x_i} )^2 } \\ &= \frac{cov(x,y) }{ var(x) } \qquad (2.12) \end{aligned} ω=i=1mxi2xii=1mxii=1myixiyii=1mxi=i=1mxi2xii=1mxixii=1mxi+i=1mxi2i=1myixiyii=1mxixii=1myi+i=1myixi=i=1m(xixi)2i=1m(xixi)(yiyi)=var(x)cov(x,y)(2.12)
    联立可得ω,b的第三种表达形式:
    ω = c o v ( x , y ) v a r ( x ) = ∑ i = 1 m ( x i − x i ‾ ) ( y i − y i ‾ ) ∑ i = 1 m ( x i − x i ‾ ) 2 b = y i ‾ − ω ∗ x i ‾ ( 2.13 ) \begin{aligned} ω = \frac{cov(x,y) }{ var(x) }=\frac{ \sum_{i=1}^{m}( x_i -\overline{x_i})( y_i - \overline{y_i}) }{ \sum_{i=1}^{m} (x_i- \overline{x_i} )^2 } \qquad b=\overline{y_i} - ω*\overline{x_i} \qquad (2.13) \end{aligned} ω=var(x)cov(x,y)=i=1m(xixi)2i=1m(xixi)(yiyi)b=yiωxi(2.13)

    2.2 矩阵求解

    除了上述方程组的求解方法,还可以利用矩阵方法来求解。对于原拟合函数,同样可写成:
    y = ω ∗ x i + b = ω 0 + ω 1 ∗ x \begin{aligned} y &=ω* x_i+b \\ &=ω_0+ω_1* x \\ \end{aligned} y=ωxi+b=ω0+ω1x
    对于m个样本,则相应的矩阵表达式为:
    Y = X ω \begin{aligned} Y &= Xω \\ \end{aligned} Y=Xω
    式中:
    Y = [ y 1 y 2 ⋮ y m ] X = [ 1 x 1 1 x 2 ⋮ 1 x m ] ω = [ ω 0 ω 1 ] \begin{aligned} Y= \left[ \begin{matrix} y_1 \\ y_2 \\ \vdots \\ y_m \end{matrix} \right] \qquad X= \left[ \begin{matrix} 1&x_1 \\ 1&x_2 \\ \vdots \\ 1&x_m \end{matrix} \right] \qquad ω= \left[ \begin{matrix} ω_0 \\ ω_1 \end{matrix} \right] \end{aligned} Y=y1y2ymX=111x1x2xmω=[ω0ω1]
    进而可得:
    L = ∑ i = 1 m ( y i − x i T ω ) 2 = ( Y − X ω ) T ( Y − X ω ) = ( Y − X ω ) T Y − ( Y − X ω ) X ω = Y T Y − ω T X T Y − Y T X ω + ω T X T X ω ( 2.14 ) \begin{aligned} L &=\sum_{i=1}^{m}(y_i-x_i^Tω)^2 \\ &=(Y - Xω)^T(Y - Xω)\\ &=(Y - Xω)^TY - (Y - Xω)Xω\\ &=Y^TY - ω^TX^TY - Y^TXω+ω^TX^TXω \qquad (2.14) \end{aligned} L=i=1m(yixiTω)2=(YXω)T(YXω)=(YXω)TY(YXω)Xω=YTYωTXTYYTXω+ωTXTXω(2.14)
    根据矩阵求导的几个重要公式及性质:
    ∂ X T A X ∂ X = 2 A X ∂ X T A ∂ X = A ∂ A X ∂ X = A T \begin{aligned} \frac{\partial X^TAX}{\partial X} =2AX \qquad \frac{\partial X^TA}{\partial X} =A \qquad \frac{\partial AX}{\partial X} =A^T \qquad \end{aligned} XXTAX=2AXXXTA=AXAX=AT
    则式对(2.14)求导可得:
    ∂ L ∂ ω = ∂ Y T Y − ω T X T Y − Y T X ω + ω T X T X ω ∂ ω = − 2 X T Y + 2 X T X ω \begin{aligned} \frac{\partial L}{\partial ω} &=\frac{\partial Y^TY - ω^TX^TY - Y^TXω+ω^TX^TXω}{\partial ω} \\ &= -2X^TY +2X^TXω \\ \end{aligned} ωL=ωYTYωTXTYYTXω+ωTXTXω=2XTY+2XTXω
    令该导数为零,当 X T X X^TX XTX可逆,则有:
    − 2 X T Y + 2 X T X ω = 0 X T X ω = X T Y ω = ( X T X ) − 1 X T Y ( 2.15 ) \begin{aligned} -2X^TY +2X^TXω &= 0\\ X^TXω &= X^TY \\ ω &= ( X^TX)^{-1}X^TY \qquad (2.15)\\ \end{aligned} 2XTY+2XTXωXTXωω=0=XTY=(XTX)1XTY(2.15)

    2.3 模型评估

    基于线性回归拟合得到的模型之后,很重要的一点就是如何评估该线性回归模型对给定数据的拟合程度?
    关于该问题,在回归算法通常采用决定系数(coefficient ofdetermination) R 2 R^2 R2来评估。以下给出 R 2 R^2 R2的相关概念定义。
    总平方和 S S R t o t SSR_{tot} SSRtot S S R t o t = ∑ i = 1 m ( y i − y i ‾ ) SSR_{tot} = \sum_{i=1}^{m}(y_i- \overline{y_i}) SSRtot=i=1m(yiyi)
    回归平方和 S S R r e g SSR_{reg} SSRreg S S R r e g = ∑ i = 1 m ( f ( x i ) − y i ‾ ) SSR_{reg} = \sum_{i=1}^{m}(f(x_i)- \overline{y_i}) SSRreg=i=1m(f(xi)yi)
    残差平方和 S S R r e s SSR_{res} SSRres S S R r e g = ∑ i = 1 m ( y i − f ( x i ) ) SSR_{reg} = \sum_{i=1}^{m}(y_i-f(x_i)) SSRreg=i=1m(yif(xi))
    决定系数 R 2 R^2 R2 R 2 = 1 − S S R r e s S S R t o t R^2 = 1 - \frac{SSR_{res}}{SSR_{tot}} R2=1SSRtotSSRres
    S S R r e s SSR_{res} SSRres表征的是真实数据和回归数据的误差, S S R t o t SSR_{tot} SSRtot表征的是真实数据和其平均值的误差, S S R r e s SSR_{res} SSRres一般情况下比 S S R t o t SSR_{tot} SSRtot小,其比值一般在0-1之间。当回归拟合越准确,则 S S R r e s SSR_{res} SSRres越小, R 2 R^2 R2越接近于1;当拟合越不准确,则 S S R r e s SSR_{res} SSRres越大, R 2 R^2 R2越接近于0。
    R 2 R^2 R2表征了自变量x对因变量y的解释程度,当自变量引起的变动占总变动的百分比高,则观察点在回归直线附近越密集,也就是回归拟合度越好。

    3. 实战

    问题描述:
    假设某披萨店的披萨价格和披萨直径之间有下列数据关系:

    IDDiameterPrice
    167.0
    289.0
    31013.0
    41417.5
    51818.0

    其中 Diameter 为披萨直径,单位为“英寸”;Price 为披萨价格,单位为“美元”。
    根据以上训练数据,来预测任一直径的披萨的价格。

    要分析该问题,我们首先可以使用 matplotlib 画出数据的散点图,x 轴表示披萨直径,y 轴表示披萨价格。由此可以直观的查看和分析数据信息。

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    from sklearn.linear_model import LinearRegression
    
    # 读取数据
    pizza = pd.read_csv("pizza.csv", index_col='Id')
    pizza.head()
    
    # 定义绘图
    def runplt():
        plt.figure()
        plt.scatter(dia, price, c='r', marker='o')  # 绘制散点图
        plt.title("Pizza price plotted against diameter")
        plt.xlabel("Diameter")
        plt.ylabel("Price")
        plt.grid(True)
        plt.xlim(0,25)
        plt.ylim(0,25)
        return plt
    	
    # 获取pizza尺寸、价格数据
    dia = pizza.loc[:,'Diameter'].values 
    price = pizza.loc[:,'Price'].values
    
    # 绘制散点图
    plt = runplt()
    plt.show()
    

    绘制得到的数据视图如下:

    在这里插入图片描述

    基于以上训练数据散点图可容易看出,其分布具备线性关系,由此我们可以假设披萨的直径和价格关系可用线性回归模型表示: f ( x ) = ω ∗ x + b f(x)=ω* x+b f(x)=ωx+b,这里 x 指披萨的直径,f(x) 为预测的披萨的价格。根据2.1章节的方程组推导公式,求解参数ω,b。
    实现代码如下:

    # 解法一 公式(2.10) :
    # w = np.sum(price * (dia - np.mean(dia))) / (np.sum(dia**2) - (1/dia.size) * (np.sum(dia))**2)
    # b = (1 / dia.size) * np.sum(price - w * dia)
    
    #解法二 公式(2.13):
    variance = np.var(dia, ddof=1)  # 计算方差,doff为贝塞尔(无偏估计)校正系数
    covariance = np.cov(dia, price)[0][1]  # 计算协方差
    w = covariance / variance
    b = np.mean(price) - w * np.mean(dia)
    print("w = %f\nb = %f" % (w, b))
    y_pred = w * dia + b # 拟合曲线
    # 拟合曲线
    plt = runplt()
    plt.plot(dia, y_pred, 'b-')
    plt.show()
    

    输出结果如下:

    w= 0.976293
    b= 1.965517
    

    绘图如下:
    在这里插入图片描述

    也可以根据2.2章节的矩阵求解推导公式,求解回归系数。

    # 解法三:矩阵求解
    def standRegres(xArr,yArr):
        xMat = mat(xArr); yMat = mat(yArr).T
        xTx = xMat.T*xMat
        if linalg.det(xTx) == 0.0:
            print("矩阵为奇异矩阵,不能求逆")
            return
        # 计算回归系数
        ws = xTx.I * (xMat.T*yMat)
        return ws
    dia1 = np.vstack([np.ones(len(dia)), dia]).T # 增加单位1的首列
    regrescoeff = standRegresMatirx(dia1,price)  # 回归系数
    print(regrescoeff)
    

    输出结果如下:

     [[1.96551724]
     [0.9762931 ]]
    

    易知矩阵解法和方程组求解获得同样的回归系数。

    也可以直接调用sklearn库,使用linear_model中线性回算法模型,关键代码如下:

    解法四:sklearn.linear_model 线性回归模型求解
    model = LinearRegression() #创建模型
    x_train = dia.reshape((-1,1)) # 数据转换成1列
    y_train = price
    model.fit(x_train,y_train) # 用训练集来训练出线型回归模型
    print("回归系数:", model.coef_, "   截距:", model.intercept_)
    
    x_test = [[0], [10], [22]] # 取3个预测值
    y_pred2 = model.predict(x_test) # 进行预测
    print("预测值:",y_pred2)
    
    plt = runplt()
    plt.plot(x_test, y_pred2, 'g-',label='sklearn') #绘制拟合曲线
    plt.plot(dia, y_pred, 'b--',label='standRegres')
    plt.legend(loc='upper left')
    plt.show()
    
    # 模型评估
    x_test = [[8], [9], [11], [16], [12]]
    y_test = [[11], [8.5], [15], [18], [11]]
    
    print("======== 模型评价 R^2 ========")
    print("Training R^2 = ", model.score(x_train, y_train))
    print("Test R^2 = ", model.score(x_test, y_test))
    

    输出结果如下:

    回归系数: [0.9762931]    截距: 1.965517241379315
    预测值: [ 1.96551724 11.72844828 23.44396552]
    ======== 模型评价 R^2 ========
    Training R^2 =  0.9100015964240102
    Test R^2 =  0.6620052929422553
    

    由于该回归模型本身基于训练数据集拟合得来,所以可以看到该回归模型对训练数据拟合较好,但对测试数据的拟合程度并没那么好。
    输出的绘图如下:
    在这里插入图片描述
    可以看到两条拟合直线重合,即我们之前求解回归系数得到的回归模型与使用sklearn库求出的回归模型是相同的。

    4. 参考学习的书目及论文

    本人在学习过程中,主要参考的相关书籍等材料在此也列出并标注相应章节,由于本人来自汽车行业,知识技术的学习及理解运用的目的始终是希望围绕联系具体的自身业务领域,所以也给出阅读学习的一些汽车方面相关机器学习的硕博论文以作参考。

    1. 机器学习算法视频 - 邹博
    2. 《线性回归分析导论》机械工业出版社
    3. 《线性代数 - 吴传生》第3章 矩阵的运算
    4. 《机器学习实战》第8章 预测数值型数据:回归
    5. 《机器学习之路》第2章 机器学习进阶:调试模型
    6. 《机器学习 - 周志华》第3章 线性模型
    7. 《基于机器学习方法的打车需求量预测研究》魏楷聪 2019 硕士论文 - 第4章 基于线性回归和样条曲线的变化趋势提取

    =文档信息=
    本学习笔记由博主整理编辑,仅供非商用学习交流使用
    由于水平有限,错误和纰漏之处在所难免,欢迎大家交流指正
    如本文涉及侵权,请随时留言博主,必妥善处置
    版权声明:非商用自由转载-保持署名-注明出处
    署名(BY) :zhudj
    文章出处:https://zhudj.blog.csdn.net/

    展开全文
  • 送五本新书《机器学习算法框架实战:Java和Python实现》,感谢机械工业出版社赞助。小编导读随着科技的迅猛发展,短短的几十年间,互联网几乎将全球的人联系了起来,世界上所发生的事件都...
  • 校宝在线出的新书《PyTorch机器学习从入门到实战》已由机械工业出版社出版!各大平台有售。 书籍详情(点击查看):机械工业出版社 | 亚马逊 | china-pub | 当当 | 京东 书籍代码地址:...
  • 人工智能的核心问题包括建构能够跟人类似甚至超卓的推理、知识、规划、学习、交流、感知、移物、使用工具和操控机械的能力等 人工智能—核心关键词 Intelligence:“The capacity to learn ..
  • 一、算法原理 k-均值算法是一种无监督学习算法。在输入数据集中不包括标签,通过k-均值算法为每个样本添加标签,相同标签样本具有共同特征。 对于数据集D={x1,x2,...,xm},划分为k个簇C1,C2,...,Ck。对象与...
  • 机器学习实践应用

    万次阅读 多人点赞 2018-04-12 10:04:41
    机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度等多门学科,专门研究计算机怎样模拟或实现人类的学习行为。机器学习是人工智能的核心,是使计算机具有 智能的根本途径。 本书通过对...
  • 机器学习实战之路 —— 1 线性回归二1. 欠拟合和过拟合问题2. 模型优化2.1 局部加权线性回归(LWLR)2.2 岭回归2.3 Lasso回归2.4 前向逐步回归2.5 时间序列分析ARIMA3. 实战:广告花费与销售额3.1 线性回归3.2 岭回归...
  • 【导读】:全面介绍机器学习发展的历史,从感知机、神经网络、决策树、SVM、Adaboost到随机森林、Deep Learning。 自科学技术和人工智能最初发展开始,科学家Blaise Pascal和Von Leibniz就思考着如何制造一台像...
  • 一 贝叶斯定理  设X是数据样本,用n个属性集...《机器学习实战》 Peter Harrington 著 人民邮电出版社 【2】 《机器学习》 周志华 著 清华大学出版社 【3】《数据挖掘概念与技术》 Jiawei Han等 著 机械工业出版社
  • 书名:机器学习实战-基于Scikit-Learn和TensorFlow 作者:(法)奥雷利安·杰龙(Aurélien Géron) 出版社:机械工业出版社 出版时间:2018年08月 从实践出发,手把手教你从零开始搭建起一个神经网络 去当当网了解 ....
  • 我们以前给大家介绍过杨强教授团队所著的业界首本联邦学习的书籍,现在这本书的实战版来了,5月刚刚出版,本次给大家赠送3本新书,即《联邦学习实战》。这是一本什么样的书所谓联邦学习技术,是一种新...
  • 传说中的机器学习“四大名著”中最适合入门的一本——“蜥蜴书”新版来了!这本书的英文原版是美国亚马逊AI霸榜图书,在人工智能、计算机神经网络、计算机视觉和模式识别三大榜单中,均为榜首!国内...
  • 出版社:机械工业出版社; 第1版 (2018年3月1日) 外文书名:Machine Learning by Scikit-learn:Algorithms and Practices 平装:207页 语种:简体中文 开本:16 ISBN:7111590244, 9787111590248 条形码:...
  • 、开发机器学习应用程序的步骤(参考机器学习实战) 图2.1 开发机器学习应用程序的步骤 如图2.1所示,书中学习和使用机器学习算法开发应用程序,通常遵循以下的步骤。 (1)收集数据。 我们可以使用很...
  • 【磐创AI导读】本文以思维导图的方式,为大家介绍了机器学习的主要知识内容,涵盖了包含机器学习算法、特征工程、机器学习实战项目、深度学习等知识。本文的主要知识内容源于七月在...
  • 分享100本Python机器学习、深度学习电子书

    千次阅读 多人点赞 2019-09-15 10:44:03
    这套电子书包括:机器学习、深度学习、数据科学入门、神经网络等 获取资源地址: https://pan.baidu.com/s/1BuY0qliHtQ86eWuBoErW3g 密码: n63r 此套电子书保持在线更新,可以在公众号:Python专栏,回复:机器学习...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,619
精华内容 647
关键字:

机器学习实战机械工业