这是小小本周的最后一篇,本周重点!文末送书,
我是小小,下面是本期文章,为您奉上!
本实例将会以一个完整的例子用来阐述一个较为简单的Python数据分析。其中Python基础部分不再讲解
这里使用numpy构建测试所用的数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(1)
N = 100
# 第一位同学, 成绩平平大约在85分左右, 比较稳定
rand1 = np.random.normal(0, 1, N)
avg1 = 85
std1 = np.rint(avg1 + rand1)
plt.plot(std1)
plt.ylim(50, 100)
plt.show()
画出折线图如下
# 第二位同学, 成绩优秀且稳步提高
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 # 有两次考试因病缺席
画出折线图
# 第三位同学, 成绩较好但波动较大
rand3 = np.random.normal(0, 5, N)
avg3 = 88
std3 = np.rint(avg3 + rand3)
# 第四位同学, 屌丝逆袭一路高歌
rand4 = np.random.normal(0, 2, N)
avg4 = 55
trend4 = np.linspace(0, 50, N)
std4 = np.rint(avg4 + rand4 + trend4)
# 第五位同学, 不断努力,但受某些外部因素干扰,成绩上升且具有周期性
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)
这里全部显示
# 多子图显示多个同学的成绩曲线
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
df = pd.DataFrame({
'student1': std1, 'student2': std2, 'student3': std3, 'student4': std4, 'student5': std5})
df.to_csv('student_score_raw.csv')
这里使用 pandas 库对数据进行处理
df = pd.read_csv('student_score_raw.csv', index_col=0) # 第一例作为行索引,默认使用第一行作为列索引
df.head()
# 查看统计信息,可以看到哪个同学波动较大,哪个同学平均分较高等,却很难像曲线图那样直观看出各个同学的分数趋势
df.describe()
df.plot(figsize=(10, 5))
# 将超过100分的数据设置为100分满分
df[df > 100] = 100
# 处理缺失值, 用缺失值前面的有效值从前往后填补
df = df.fillna(method='ffill', axis=0)
df.plot(figsize=(10, 5))
# 通过曲线可以直观看出:
# student1: 成绩一般,且很稳定
# student2: 成绩优秀,且稳步上升
# studeng3: 成绩一般,且波动很大
# student4: 屌丝逆袭,一路高歌
# student5: 一直进步,但具有一些周期性
# 和当初的数据设计吻合
df.to_csv('student_score.csv')
这里使用keras进行训练模型,实现对数据的预测
# 使用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
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))
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
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)
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)
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
def model_fit(model, train_x, train_y):
'''训练模型'''
model.fit(train_x, train_y, epochs=30, batch_size=1, verbose=2)
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
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)
# 预测未来五次成绩
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)
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()
文末送书时刻!小小为粉文末送书,此时送的书是Python数据科学实践。
在此感谢北京大学出版社的支持,本次送书由北京大学出版社支持。
老规矩,从留言区中选中奖者,按照点赞数选择,点赞数高者获得书一本,累计送书三本。时间截止9月13日的18点。
小明菜市场
推荐阅读
● 优雅 | 今天很水的文章-Excel导入导出
● 理论 | 当 Spring Boot 遇上了消息队列......
● 实践 | kafka 基本使用
● 搭建 | 一步成功搭建Centos + Kubernetes 环境
● 震惊 | 某公司实习生跑路,竟为了学习偷盗面试题