机器学习项目练习:基于Scikit-Learn的专利创新性的回归预测

548 阅读6分钟

前言


  • 本人想要动手练习一下机器学习项目,又恰好遇到期末各种论文来袭,遂与期末论文结合了一下。
  • 为了对专利的创新性进行预测分析,借助国内外研究证实过的创新强度指标,利用专利的年龄、发明人团队规模、知识异质性、合作异质性等专利自有属性,对创新强度进行预测。
  • 摸索学习中,如有错误欢迎指正,谢谢

1. 数据来源及项目描述


本文以美国专利局建立的 UTPTO 专利数据库作为数据来源库,以其中的分子生物学和微生物学类(美国分类大类为435)专利为研究样本,共有34154条发明专利数据及其相关著录信息,如专利号、题名、摘要、授权日、美国分类号(CCL)、发明人、发明人所在城市和参考文献(仅限参考的专利文献)等信息。 为了对专利的创新性进行预测分析,借助国内外研究证实过的创新强度指标,利用专利的类型、发明人团队规模、专利引用数量、知识异质性、合作异质性等五个专利自有属性(以查阅相关文献,表明这些指标与创新性具有一定的相关性),利用机器学习回归方法对创新强度进行预测。 所以在原始数据集的基础上,提取了每条专利信息的专利的类型(CCL)、发明人团队规模(INVT_NUM)、专利引用数量(REF_NUM)、知识异质性(DIF_REF)、合作异质性(DIF_CIT)这五个指标,以及创新强度值(CD),如下图所示

2. 准备并初步分析数据


# 导入数据
import pandas as pd
patents = pd.read_excel('435classdatav5.xlsx')
# 查看数据基本信息
patents.info()

# 数据集描述性统计
patents.describe()

# 删除编号列
patents.drop("NO", axis=1, inplace=True)
# 画图直观分析各属性情况
import matplotlib.pyplot as plt


%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


patents.hist(bins=50, figsize=(20,15))
plt.show()

直观看来,创新强度CD与其他几个指标的相关性不大

# 计算相关性
corr_matrix=patents.corr()
corr_matrix["CD"].sort_values(ascending=False)

3.数据预处理

分开训练集和测试集

因为数据集所包含的分类号属性属于离散型变量,为保证训练集与测试集正常发挥作用,这里按照分类号以8:2的比例进行分层抽样。

#分层抽样,按分类号
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)

for train_index, test_index in split.split(patents, patents["CCL"]):
    strat_train_set = patents.loc[train_index]
    strat_test_set = patents.loc[test_index]
# 查看数据结构
print(strat_train_set.shape,
      '\n',strat_test_set.shape)
(27323, 6) 
 (6831, 6)

首先分开特征和目标标签,以CD作为标签,其他作为特征。

#删除标签
patenting = strat_train_set.drop("CD", axis=1) 
#创建训练副本
patenting_labels = strat_train_set["CD"].copy()

数据清洗

在正式的模型训练之前还要做一些数据处理:

  1. 空值的处理
  2. 异常值的处理
  3. 离散变量处理 对于缺失值,可以去掉含有缺失值的个体(dropna)、去掉含缺失值的整个特征(drop)、给缺失值补上一些值(0,平均值、中位数等)(fillna)

处理文本特征

文本属性不能直接传入训练,在这个项目中的分类号属性就是属于文本属性,在这里可以使用One Hot编码。

自定义Transformer

Scikit-Learn中的函数中提供的Transformer方法不一定适用于真实情况,有时候需要自定义一个Transformer.定义类时,需要加入基础类,BaseEstimator,以及TransformerMixin(用于生成fit_transformer()方法)。 而且上面提到的这些数据转换操作,可以借助Pipeline类来帮助这一系列的转换,并封装。

try:
    from sklearn.impute import SimpleImputer # Scikit-Learn 0.20+
except ImportError:
    from sklearn.preprocessing import Imputer as SimpleImputer


from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

num_pipeline = Pipeline([
        #median补缺失值策略
        ('imputer', SimpleImputer(strategy="median")),      
        #StandardScaler标准化转换器
        ('std_scaler', StandardScaler()),
    ])
try:
    from sklearn.preprocessing import OrdinalEncoder # just to raise an ImportError if Scikit-Learn < 0.20
    from sklearn.preprocessing import OneHotEncoder
except ImportError:
    from future_encoders import OneHotEncoder # Scikit-Learn < 0.20
num_attribs = list(patenting_num)
cat_attribs = ['CCL']
full_pipeline = ColumnTransformer([
        ("num", num_pipeline, num_attribs),
        #文本特征到独热编码转换
        ("cat", OneHotEncoder(), cat_attribs),
    ])
patenting_prepared = full_pipeline.fit_transform(patenting)

4. 模型训练

决策树回归

from sklearn.tree import DecisionTreeRegressor
#使用决策树回归
tree_reg = DecisionTreeRegressor(random_state=42)
tree_reg.fit(patenting_prepared, patenting_labels)

from sklearn.metrics import mean_squared_error
import numpy as np
#决策树的误差
patenting_predictions = tree_reg.predict(patenting_prepared)
tree_mse = mean_squared_error(patenting_labels, patenting_predictions)
tree_rmse = np.sqrt(tree_mse)
print(tree_rmse)

0.1222348604334857

#使用交叉验证来进行评估——决策树回归
from sklearn.model_selection import cross_val_score

scores = cross_val_score(tree_reg, patenting_prepared, patenting_labels,
                         scoring="neg_mean_squared_error", cv=10)
tree_rmse_scores = np.sqrt(-scores)
#显示决策树交叉验证的结果
def display_scores(scores):
    print("Scores:", scores)
    print("Mean:", scores.mean())
    print("Standard deviation:", scores.std())
display_scores(tree_rmse_scores)

Scores: [0.23523046 0.23163885 0.23027035 0.23314598 0.25142486 0.23322703 0.24014534 0.24452541 0.23922923 0.23047444] Mean: 0.23693119435252902 Standard deviation: 0.006544897283615564

随机森林回归

from sklearn.ensemble import RandomForestRegressor
#随机森林回归
forest_reg = RandomForestRegressor(n_estimators=30, max_features=8,random_state=42)
forest_reg.fit(patenting_prepared, patenting_labels)
#使用交叉验证来进行评估——随机森林回归
from sklearn.model_selection import cross_val_score

forest_scores = cross_val_score(forest_reg, patenting_prepared, patenting_labels,
                                scoring="neg_mean_squared_error", cv=10)
forest_rmse_scores = np.sqrt(-forest_scores)
display_scores(forest_rmse_scores)

Scores: [0.20408526 0.22027575 0.20893746 0.21425075 0.20945561 0.19779428 0.22585026 0.20252916 0.21406977 0.21369368] Mean: 0.21109419959839934 Standard deviation: 0.007964464578674136

#决策树回归在测试集上的效果
final_model=tree_reg
X_test = strat_test_set.drop("CD", axis=1)
y_test = strat_test_set["CD"].copy()
X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_model.predict(X_test_prepared)

final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
print(final_rmse)

0.23717729756390787

随机森林模型参数调整

#网格搜索
from sklearn.model_selection import GridSearchCV

param_grid = [
    # try 12 (3×4) combinations of hyperparameters
    {'n_estimators': [10,30], 'max_features': [2,4,6,8]},
    # then try 6 (2×3) combinations with bootstrap set as False
    {'bootstrap': [False], 'n_estimators': [10, 30], 'max_features': [2, 4, 6]},
  ]

forest_reg = RandomForestRegressor(random_state=42)
# train across 5 folds, that's a total of (12+6)*5=90 rounds of training 
grid_search = GridSearchCV(forest_reg, param_grid, cv=5,
                           scoring='neg_mean_squared_error', return_train_score=True)
grid_search.fit(patenting_prepared, patenting_labels)

GridSearchCV(cv=5, estimator=RandomForestRegressor(random_state=42), param_grid=[{'max_features': [2, 4, 6, 8], 'n_estimators': [10, 30]}, {'bootstrap': [False], 'max_features': [2, 4, 6], 'n_estimators': [10, 30]}], return_train_score=True, scoring='neg_mean_squared_error')

grid_search.best_params_

{'max_features': 8, 'n_estimators': 30}

#随机森林回归在测试集上的效果
#final_model = grid_search.best_estimator_
final_model=forest_reg
X_test = strat_test_set.drop("CD", axis=1)
y_test = strat_test_set["CD"].copy()
X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_model.predict(X_test_prepared)

final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
final_rmse

0.2041034942299966

人工神经网络

from sklearn.neural_network import MLPRegressor
ann_reg = MLPRegressor(random_state=42, max_iter=100)
ann_reg.fit(patenting_prepared, patenting_labels)
ann_reg_predict = ann_reg.predict(patenting_prepared)
#使用交叉验证来进行评估——人工神经网络
from sklearn.model_selection import cross_val_score

ann_reg_scores = cross_val_score(ann_reg, patenting_prepared, patenting_labels,
                                scoring="neg_mean_squared_error", cv=10)
ann_reg_rmse_scores = np.sqrt(-ann_reg_scores)
display_scores(ann_reg_rmse_scores)

Scores: [0.19838524 0.21552342 0.20064441 0.20629559 0.20471131 0.19499855 0.21604244 0.19780061 0.20117999 0.20474261] Mean: 0.20403241846550388 Standard deviation: 0.006740346518995299

#在测试集上的效果
final_model = ann_reg
X_test = strat_test_set.drop("CD", axis=1)
y_test = strat_test_set["CD"].copy()
X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_model.predict(X_test_prepared)

final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
print(final_rmse)

0.20358969321799883

5. 小结


不同模型的效果对比:

---训练集验证集测试集
决策树回归0.12230.13380.1678
随机森林回归0.23960.21110.2040
人工神经网络0.23720.20410.2035

从表格中各模型在训练集、验证集和测试集的均方根误差可以发现,这三个算法的表现效果相近,没有较大的差距,在训练集上表现效果,最好其次是测试集,表现最差的是在交叉验证集上。

在测试集上的均方误差约为0.2,说明专利的著录信息以及后向引用特征可以在一定程度上对专利的创新强度进行预测。

决策树回归算法在训练集上表现最好,而在验证集和测试集上 表现最差,可以说明决策树回归可能存在着过拟合的问题。人工神经网络算法在训练集上表现较差,而在验证集和测试集上表现最好。

但从测试机的均方误差来看,决策树算法是这三个机器学习算法中的最优模型,其次是人工神经网络回归和随机森林回归。

但是,这个项目里只用了5个属性,是因为专利的可提取属性有限,如果发现更多可用来进行预测属性变量,也许会提高预测精度。