前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python数据科学实践

Python数据科学实践

原创
作者头像
leland
发布2020-02-09 11:55:59
1.1K0
发布2020-02-09 11:55:59
举报
文章被收录于专栏:leland的专栏

本文使用一个完整的例子来理解python数据科学,例子用到numpy/pandas/matplotlib/keras这些和数据科学相关的python库,实现数据预处理、分析、时间序列模型训练及预测一整个流程。最终目的是帮助理解python数据科学的一般过程,以及熟悉python相关科学计算库的使用。

1、构造实验用数据

使用numpy构建一个班级5位同学N次数学考试的成绩, 同学成绩需要有上升趋势、下降趋势、平稳、严重抖动。

代码语言:javascript
复制
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

np.random.seed(1)
N = 100

1.1 构造第1位同学成绩

代码语言:javascript
复制
# 第一位同学, 成绩平平大约在85分左右, 比较稳定
rand1 = np.random.normal(0, 1, N)
avg1 = 85
std1 = np.rint(avg1 + rand1)
plt.plot(std1)
plt.ylim(50, 100)
plt.show()
图1-1 第一位同学成绩趋势图
图1-1 第一位同学成绩趋势图

1.2 构造第2位同学成绩

代码语言:javascript
复制
# 第二位同学, 成绩优秀且稳步提高
rand2 = np.random.normal(0, 1, N)
avg2 = 90
trend2 = np.linspace(0, 10, N)
std2 = np.rint(avg2 + rand2 + trend2)    # 故意产出可能出现异常值的情况,后面数据预处理统一处理
std2[10] = np.nan
std2[13] = np.nan    # 有两次考试因病缺席
图1-2 第二位同学成绩趋势图
图1-2 第二位同学成绩趋势图

1.3 构造第3位同学成绩

代码语言:javascript
复制
# 第三位同学, 成绩较好但波动较大
rand3 = np.random.normal(0, 5, N)
avg3 = 88
std3 = np.rint(avg3 + rand3)
图1-3 第三位同学成绩趋势图
图1-3 第三位同学成绩趋势图

1.4 构造第4位同学成绩

代码语言:javascript
复制
# 第四位同学, 屌丝逆袭一路高歌
rand4 = np.random.normal(0, 2, N)
avg4 = 55
trend4 = np.linspace(0, 50, N)
std4 = np.rint(avg4 + rand4 + trend4)
图1-4 第四位同学成绩趋势图
图1-4 第四位同学成绩趋势图

1.5 构造第5位同学成绩

代码语言:javascript
复制
# 第五位同学, 不断努力,但受某些外部因素干扰,成绩上升且具有周期性
rand5 = np.random.normal(0, 1, N)
avg5 = 72
trend5 = np.linspace(0, 20, N)
period5 = 3 * np.sin(np.linspace(0, 100, N))
std5 = np.rint(avg5 + rand5 + trend5 + period5)
图1-5 第五位同学成绩趋势图
图1-5 第五位同学成绩趋势图

1.6 多子图显示多个同学的成绩曲线

代码语言:javascript
复制
# 多子图显示多个同学的成绩曲线
fig, ax = plt.subplots(2, 3, sharex='col', sharey='row', figsize=(20, 10))
plt.ylim(50, 110)
total = {'student1': std1, 'student2': std2, 'student3': std3, 'student4': std4, 'student5': std5}
keys = list(total.keys())
index = 0
for i in range(2):
    for j in range(3):
        try:
            key = keys[index]
        except Exception as e:
            pass
        else:
            std_score = total[key]
            ax[i, j].plot(std_score, label=key)
            ax[i, j].legend()
            index += 1
图1-6 构造的五位同学成绩趋势图总览
图1-6 构造的五位同学成绩趋势图总览

1.7 数据写入文件保存

最后将上面构造的实验数据通过pandas的to_csv函数写入到文件中保存。

代码语言:javascript
复制
df = pd.DataFrame({
    'student1': std1, 'student2': std2, 'student3': std3, 'student4': std4, 'student5': std5})
df.to_csv('student_score_raw.csv')

2、数据分析及预处理

使用pandas对实验数据进行一些处理。

2.1 使用pandas读取实验数据

代码语言:javascript
复制
df = pd.read_csv('student_score_raw.csv', index_col=0)    # 第一例作为行索引,默认使用第一行作为列索引
df.head()
图2-1 使用pandas读取数据
图2-1 使用pandas读取数据

2.2 查看各个同学成绩的概况

代码语言:javascript
复制
# 查看统计信息,可以看到哪个同学波动较大,哪个同学平均分较高等,却很难像曲线图那样直观看出各个同学的分数趋势
df.describe()
图2-2 显示各个同学成绩的统计信息
图2-2 显示各个同学成绩的统计信息

2.3 剔除脏数据

代码语言:javascript
复制
df.plot(figsize=(10, 5))
图2-3 存在数据缺失和超分的异常数据
图2-3 存在数据缺失和超分的异常数据
代码语言:javascript
复制
# 将超过100分的数据设置为100分满分
df[df > 100] = 100
# 处理缺失值, 用缺失值前面的有效值从前往后填补
df = df.fillna(method='ffill', axis=0)
df.plot(figsize=(10, 5))
图2-4 处理完缺失数据和异常数据后的趋势图
图2-4 处理完缺失数据和异常数据后的趋势图
代码语言:javascript
复制
# 通过曲线可以直观看出:
# student1: 成绩一般,且很稳定
# student2: 成绩优秀,且稳步上升
# studeng3: 成绩一般,且波动很大
# student4: 屌丝逆袭,一路高歌
# student5: 一直进步,但具有一些周期性
# 和当初的数据设计吻合
df.to_csv('student_score.csv')

3、成绩预测

抽取一个同学的成绩序列, 使用深度学习库keras,训练预测模型, 预测下一次的分数,并评估预测效果。

代码语言:javascript
复制
# 使用keras做预测
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.metrics import mean_squared_error

3.1 获取成绩序列

代码语言:javascript
复制
def gen_data():
    '''生产用于做预测的数据'''
    df = pd.read_csv(
        'student_score.csv',
        index_col=0,
        header=0)
    return df['student5']
s = gen_data()    # 抽取student5的同学成绩做模型训练, 预测该同学未来的成绩
s.plot(figsize=(10, 5))
图3-1 第五位同学的成绩具有周期性和上升趋势
图3-1 第五位同学的成绩具有周期性和上升趋势

3.2 对数据进行归一化处理

代码语言:javascript
复制
from sklearn.preprocessing import MinMaxScaler
def preprocessing_scale(data):
    '''对数据进行归一化。
    
    args:
        data: 时序数据原始数据数组
    returns:
        dataset: 经过归一化后的时序数据
        scaler: 缩放
    '''
    scaler = MinMaxScaler(feature_range=(0, 1))
    dataset = np.array(data)
    dataset = np.reshape(dataset, (dataset.shape[0], 1))
    dataset = dataset.astype('float32')
    dataset = scaler.fit_transform(dataset)
    return dataset, scaler

3.3 将数据划分成训练集和测试集

代码语言:javascript
复制
def preprocessing_split(dataset):
    '''对数据划分训练数据和测试数据。

    args:
        dataset: 时序数据数组
    returns:
        四元祖,(dataset, train, test, scaler)
        dataset: 经过reshape和最大最小缩放后的时序数据
        train: 划分出来的训练集
        test: 划分出来的测试集
        scaler: 数据缩放对象
    '''
    train_size = int(len(dataset) * 0.66)
    test_size = len(dataset) - train_size
    train, test = dataset[0:train_size, :], dataset[train_size:, :]
    return train, test
train, test = preprocessing_split(dataset)
print(train.shape, test.shape)
# (66, 1) (34, 1)

3.4 构造可输入LSTM模型的数据

对自回归数据做滑动窗口构造训练用的特征和标签数据。

代码语言:javascript
复制
def create_dataset(dataset, look_back=1):
    '''构造用于LSTM训练的数据。

    args:
        dataset: 时序数据数组
        look_back: 步长值
    returns:
        元组,(特征x数组,标签y数组)
    '''
    dataX, dataY = [], []
    for i in range(len(dataset)-look_back):
        a = dataset[i: (i+look_back), 0]
        dataX.append(a)
        dataY.append(dataset[i+look_back, 0])
    return np.array(dataX), np.array(dataY)
x, y = create_dataset(train, 3)

3.5 构建LSTM模型

代码语言:javascript
复制
def create_lstm_model(look_back, predict_steps=1):
    '''构建lstm模型

    传入步长值,构建简单的lstm模型并返回。

    args:
        look_back: 步长值
    returns:
        model: keras的lstm模型
    '''
    model = Sequential()
    model.add(LSTM(32, input_shape=(1, look_back)))
    model.add(Dense(predict_steps))
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

3.6 模型训练

代码语言:javascript
复制
def model_fit(model, train_x, train_y):
    '''训练模型'''
    model.fit(train_x, train_y, epochs=30, batch_size=1, verbose=2)

3.7 模型预测

代码语言:javascript
复制
def model_predict(model, trainX, testX, scaler):
    '''输入训练数据和测试数据,模型输出预测结果。

    args:
        model: lstm模型
        trainX: 训练数据的特征
        testX: 测试数据的特征
        scaler: 做缩放的对象,用于将归一化的数据还原
    returns:
        二元组,(train_predict, test_predict)
        train_predict: 训练数据的预测结果
        test_predict: 测试数据的预测结果
    '''
    train_predict = model.predict(trainX)
    test_predict = model.predict(testX)
    # 归一化数据还原
    train_predict = scaler.inverse_transform(train_predict)
    test_predict = scaler.inverse_transform(test_predict)
    return train_predict, test_predict

3.8 训练模型并查看结果

代码语言:javascript
复制
look_back = 10    # 设置往回看的步长为10
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
model = create_lstm_model(look_back)
model_fit(model, trainX, trainY)
train_predict, test_predict = model_predict(model, trainX, testX, scaler)
图3-2 在训练集上的预测结果
图3-2 在训练集上的预测结果
图3-3 在测试集上的预测结果
图3-3 在测试集上的预测结果
图3-4 在训练集和测试集上各种的预测效果
图3-4 在训练集和测试集上各种的预测效果

3.9 预测未来5次成绩

代码语言:javascript
复制
# 预测未来五次成绩
predict_scores = []
times = 5
datas = dataset[-look_back:].flatten()
while times:
    datas = datas[-look_back:]
    input_datas = datas.reshape(1, 1, -1)
    print(input_datas)
    predict_score = model.predict(input_datas).flatten()
    print(predict_score)
    predict_scores.append(predict_score)
    datas = np.append(datas, predict_score)
    times -= 1
predict_scores = scaler.inverse_transform(predict_scores)
print(predict_scores)
plt.plot(predict_scores)
图3-5 预测未来的五次成绩
图3-5 预测未来的五次成绩
代码语言:javascript
复制
predict_datas = np.empty_like(dataset)
predict_datas[:, :] = np.nan
real_datas = scaler.inverse_transform(dataset)
predict_datas[-1] = real_datas[-1]
predict_datas = np.append(predict_datas, predict_scores, axis=0)
plt.plot(real_datas, label='real')
plt.plot(predict_datas, label='predict')
plt.legend()
图3-6 现有数据与未来预测数据拼接的曲线
图3-6 现有数据与未来预测数据拼接的曲线

4、实验总结

本文通过自己构造的数据,完成数据预处理及时序模型的训练预测,帮助理解python数据科学的一般过程。另外,在构造数据中熟悉了numpy的使用; 在读取数据及做数据分析及异常值处理时熟悉了pandas的使用; 通过matplotlib绘制图达到直观展示数据的效果;做时序预测时熟悉了keras的使用。基本达到了熟悉python相关科学计算库使用的目的。

有兴趣的同学可以照着代码做实验,实验环境最好是python3.x或是python2.7,直接安装使用anaconda最为便捷。

希望对你有用,谢谢。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、构造实验用数据
    • 1.1 构造第1位同学成绩
      • 1.2 构造第2位同学成绩
        • 1.3 构造第3位同学成绩
          • 1.4 构造第4位同学成绩
            • 1.5 构造第5位同学成绩
              • 1.6 多子图显示多个同学的成绩曲线
                • 1.7 数据写入文件保存
                • 2、数据分析及预处理
                  • 2.1 使用pandas读取实验数据
                    • 2.2 查看各个同学成绩的概况
                      • 2.3 剔除脏数据
                      • 3、成绩预测
                        • 3.1 获取成绩序列
                          • 3.2 对数据进行归一化处理
                            • 3.3 将数据划分成训练集和测试集
                              • 3.4 构造可输入LSTM模型的数据
                                • 3.5 构建LSTM模型
                                  • 3.6 模型训练
                                    • 3.7 模型预测
                                      • 3.8 训练模型并查看结果
                                        • 3.9 预测未来5次成绩
                                        • 4、实验总结
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档