一、显卡日志

Benchmarking #2# #4# precision type #1#

#1# model average #2# time : #3# ms

``````Benchmarking 2(Inference) 4(float) precision type 1(resnet50)
1(resnet50)  model average 2(inference) time :  3(13.426570892333984) ms
``````

问题：整理为如下样式

思路

1.观察给定的数据，首先需要做的是将数据导入进来

2.将1，2，3，4的数据提取出来

3.将2和4组合为列，1为行，3作为值

``````import pandas as pd
import numpy as np
import re
``````

【START】

1. 读取数据

``````file = open('benchmark.txt')
keyStart = 'memory_available: 129118310400'
keyEnd = 'benchmark end :  2020/12/24 12:56:47'
pat = re.compile(keyStart+'(.*?)'+keyEnd, re.S)
result = pat.findall(buff) #得到我们实际想要的数据
file.close()
``````

2.调整数据格式

``````A = result
#将数据依据\n拆分
A = A[0].split('\n')
#去除多余数据
A = A[1:len(A)-1]
# 获取奇数列和偶数列
J = [i for i in A if A.index(i)%2 == 0]
Q = [i for i in A if A.index(i)%2 == 1]
#将奇数列和偶数列拼成DataFrame
df = pd.DataFrame({
'A':J,
'B': Q})
``````
A B
0 Benchmarking Training float precision type mna... mnasnet0_5 model average train time : 28.527...
1 Benchmarking Training float precision type mna... mnasnet0_75 model average train time : 34.10...

3.提取值

A列：提取2，4 ；B列提取1，3

``````#通过正则提取到2和4
s1 = df['A']
p = 'Benchmarking( \w+)( \w+)'
ext1 = s1.str.extract(p)
s2 = df['B']
#提取到1，2，3。注意获取浮点型数据的方法
p2 = '(\w+)  model average (\w+) time :  (\d+.\d+)'
ext2 = s2.str.extract(p2)
#拼接1，2，3，4
data = pd.DataFrame({
'name': ext2[0],
'type': ext1[0]+'_'+ext1[1],
'time': round(ext2[2].astype('float'),3)})#截取为小数点后三位，注意需要转换为float型
``````
name type time
0 mnasnet0_5 Training_ float 28.528
1 mnasnet0_75 Training_ float 34.105
2 mnasnet1_0 Training_ float 34.314

4. 长表变宽表

``````data = data.pivot(index='name',columns='type',values='time')
data = data.reset_index()
``````
type name Inference_ double Inference_ float Inference_ half Training_ double Training_ float Training_ half
0 densenet121 144.111 15.637 19.772 417.207 93.357 88.976
1 densenet161 511.177 31.750 27.555 1290.287 136.624 144.319
2 densenet169 175.808 21.598 26.371 511.404 104.840 121.556
3 densenet201 223.960 26.169 33.394 654.365 129.334 118.940
4 mnasnet0_5 11.870 8.039 6.929 48.232 28.528 27.198

【END】

总结

1.首先就是读取数据，需要排除我们不要的数据，这里是在网上查找了一个获取开始和结束值之间数据的方法

2.数据获取了之后发现存的是一个长字符串，观察之后选择将数据拆分，需要注意的是要先转换为字符串之后再拆分，拆分完以后，发现我们需要的数据存成了两行，这里又将两行转换为两列

二、水压站点的特征工程

df1和df2中分别给出了18年和19年各个站点的数据，其中列中的H0至H23分别代表当天0点至23点；df3中记录了18-19年的每日该地区的天气情况，请完成如下的任务：

``````df1 = pd.read_csv('yali18.csv')
``````
``````df1.tail(2)
``````
Time MeasName H0 H1 H2 H3 H4 H5 H6 H7 ... H14 H15 H16 H17 H18 H19 H20 H21 H22 H23
10948 2018-12-31 站点9 0.287250 0.301875 0.30600 0.30525 0.313500 0.301500 0.279750 0.253875 ... 0.241500 0.237750 0.233625 0.227625 0.209625 0.226500 0.21975 0.211500 0.241125 0.246375
10949 2018-12-31 站点6 0.313125 0.330375 0.33375 0.33450 0.337125 0.326625 0.310875 0.277875 ... 0.261375 0.259125 0.262125 0.252750 0.241500 0.252375 0.24675 0.239625 0.269250 0.269625

2 rows × 26 columns

``````df2.head(2)
``````
Time MeasName H0 H1 H2 H3 H4 H5 H6 H7 ... H14 H15 H16 H17 H18 H19 H20 H21 H22 H23
0 2019-01-01 站点4 0.342000 0.429375 0.4290 0.44025 0.445875 0.444750 0.417750 0.387000 ... 0.319875 0.32625 0.323625 0.322500 0.309000 0.307125 0.307125 0.307125 0.307125 0.307125
1 2019-01-01 站点7 0.215125 0.239500 0.2575 0.24625 0.275125 0.264625 0.229375 0.205375 ... 0.180625 0.17650 0.181375 0.155125 0.159625 0.146125 0.144625 0.135250 0.158875 0.184750

2 rows × 26 columns

1. 通过df1和df2构造df，把时间设为索引，第一列为站点编号，第二列为对应时刻的压力大小

思路

【START】

1. 拼接数据

``````df = pd.concat([df1,df2],axis=0,join='outer')
``````
Time MeasName H0 H1 H2 H3 H4 H5 H6 H7 ... H14 H15 H16 H17 H18 H19 H20 H21 H22 H23
0 2018-01-01 站点4 0.402750 0.407625 0.418125 0.425250 0.426 0.42525 0.417375 0.426375 ... 0.348750 0.35925 0.35550 0.34425 0.352125 0.35625 0.34725 0.343875 0.356625 0.418875
1 2018-01-01 站点7 0.214375 0.226750 0.232375 0.233125 0.235 0.23275 0.230875 0.220000 ... 0.187375 0.19675 0.19975 0.19225 0.186250 0.18325 0.17725 0.163375 0.165250 0.199375

2 rows × 26 columns

2. 将H0-H23替换为时间值

``````#1.使用正则将H去除
timet = pd.Series(df.columns[2:])
p = 'H(\d+)'
timet = timet.str.extract(p)[0].to_list()
#2.在前面填充0，否则在后面拼接的时候0:00:00不显示
timet = [' '+i.zfill(2)+':00:00' for i in timet]
``````
``````#3.替换原来的列名，这里将列名补全，可以直接替换
timet1 = ['Date','站点']+timet
df.columns = timet1
``````
Date 站点 00:00:00 01:00:00 02:00:00 03:00:00 04:00:00 05:00:00 06:00:00 07:00:00 ... 14:00:00 15:00:00 16:00:00 17:00:00 18:00:00 19:00:00 20:00:00 21:00:00 22:00:00 23:00:00
0 2018-01-01 站点4 0.402750 0.407625 0.418125 0.425250 0.426 0.42525 0.417375 0.426375 ... 0.348750 0.35925 0.35550 0.34425 0.352125 0.35625 0.34725 0.343875 0.356625 0.418875
1 2018-01-01 站点7 0.214375 0.226750 0.232375 0.233125 0.235 0.23275 0.230875 0.220000 ... 0.187375 0.19675 0.19975 0.19225 0.186250 0.18325 0.17725 0.163375 0.165250 0.199375

2 rows × 26 columns

3.将宽表变为长表

``````#转换为长表，然后将日期和时间拼接为一个字段
df_melted = df.melt(id_vars=['Date','站点'],
value_vars=timet,
var_name='Time2',
value_name='压力')
df_melted['Time'] = pd.to_datetime(df_melted['Date']+df_melted['Time2'])
df_new = df_melted[['Time','站点','压力']]
#将Time作为索引
df_new = df_new.set_index('Time')
df_new.tail(3)
``````

Time
2019-12-31 23:00:00 站点2 0.332000
2019-12-31 23:00:00 站点9 0.201375
2019-12-31 23:00:00 站点6 0.000000

【END】

2. 在上一问构造的df基础上，构造下面的特征序列或DataFrame，并把它们逐个拼接到df的右侧

2.1 当天最高温、最低温和它们的温差

``````df3.head(3)
``````

0 2018-01-01 多云 1C～-4C 东南风 微风
1 2018-01-02 阴转多云 8C～0C 东北风 3-4级
2 2018-01-03 阴转小雪 1C～-1C 东北风 4-5级转4-5级

【START】

思路

``````#删除气温为空的值
df_t = df3.dropna(how='any',subset=['气温'])
s = df_t['气温']
#将空格和℃替换为统一值，方便正则取值
s = s.str.replace(' ','')
s = s.str.replace('℃','C')
#正则表达式取出温度
p = '(\d+)C～(\S\d+|\d+)'
ext = s.str.extract(p)
#由于存在没有最低温度的值，这里选择不为na的值
ext = ext[ext[0].isna()==False]
#将类型转换为int型，方便计算差值
ext[0] = ext[0].astype(int)
ext[1] = ext[1].astype(int)
ext[2] = ext[0] - ext[1]
``````
0 1 2
0 1 -4 5
1 8 0 8

``````#使用索引拼接的方式，上面删除na值不会影响到索引号
df_t = df_t.join(ext,how='outer')
#对列名重命名
df_t = df_t.rename(columns = {
0:'最高气温',1:'最低气温',2:'温差'})
df_t = df_t[['日期','最高气温','最低气温','温差']]
df_t['日期'] = pd.to_datetime(df_t['日期'])
``````
``````df_te = df_new.copy()
``````
``````#对第1小问生成的df_new进行改造，建立拼接字段date
df_m = df_te.reset_index(drop=False)
#注意使用merge的时候，两个日期的类型要一致
df_m['date'] = pd.to_datetime(df_m['Time'].dt.date)
df_l = df_m.merge(df_t, left_on = 'date', right_on='日期', how='left')
``````
``````df_l.head(2)
``````
Time 站点 压力 date 日期 最高气温 最低气温 温差
0 2018-01-01 站点4 0.402750 2018-01-01 2018-01-01 1.0 -4.0 5.0
1 2018-01-01 站点7 0.214375 2018-01-01 2018-01-01 1.0 -4.0 5.0

【END】

思路

【START】

``````df_w = df3.copy()
#日期类型转换
df_w['日期'] = pd.to_datetime(df_w['日期'])
s = df_w['天气']
s1 = s.str.contains('沙|暴')
#此处注意一定要重新命名，默认名称为天气，在join的时候会报错
s1 = s1.rename('是否沙暴')
s2 = s.str.contains('雾')
s2 = s2.rename('是否有雾')
s3 = s.str.contains('雨')
s3 = s3.rename('是否有雨')
s4 = s.str.contains('雪')
s4 = s4.rename('是否有雪')
s5 = s.str.contains('晴')
s5 = s5.rename('是否晴天')
``````
``````#将上面的结果拼接到df_w中
df_w = df_w.join(s1,how='left')
df_w = df_w.join(s2,how='left')
df_w = df_w.join(s3,how='left')
df_w = df_w.join(s4,how='left')
df_w = df_w.join(s5,how='left')
df_w.tail(2)
``````

727 2019-12-30 阴转晴 4℃～-6℃ 东北风转北风 4-5级转4-5级 False False False False True
728 2019-12-31 晴转多云 0℃～-5℃ 西风转南风 <3级 False False False False True
``````#将df_w数据拼接到df_l
df_l = df_l.merge(df_w, left_on = 'date', right_on='日期', how='left')
df_e = df_l[['Time','站点','压力','date','天气','气温','风向','最高气温','最低气温','温差','是否沙暴','是否有雾','是否有雨','是否有雪','是否晴天']]
df_e.tail(2)
``````
Time 站点 压力 date 天气 气温 风向 最高气温 最低气温 温差 是否沙暴 是否有雾 是否有雨 是否有雪 是否晴天
525598 2019-12-31 23:00:00 站点9 0.201375 2019-12-31 晴转多云 0℃～-5℃ 西风转南风 <3级 0.0 -5.0 5.0 False False False False True
525599 2019-12-31 23:00:00 站点6 0.000000 2019-12-31 晴转多云 0℃～-5℃ 西风转南风 <3级 0.0 -5.0 5.0 False False False False True

【END】

思路

【START】

``````#筛选出有雨的数据
df_y = df_e[df_e['是否有雨']==True]
gb = df_y.groupby('date')['压力'].max()
``````
``````#依据gb的最大值和最小值来进行分组，分为小、中、大、特大四类
print(gb.min())
print(gb.max())
``````
``````0.40424999594688416
1.4006251096725464
``````
``````#对雨量进行分类
s = pd.cut(gb, bins=4, labels=['小','中','大','特大'])
``````

``````#筛选出有雪的数据
df_x = df_e[df_e['是否有雪']==True]
pat = '(\w雪)'
typ = df_x['天气'].str.extract(pat)
typ[0].unique()
#我们发现提取后，雪的分类可以设置为四类，现在需要将四类作为有序分类
``````
``````array(['小雪', '中雪', '夹雪', '大雪'], dtype=object)
``````
``````#设置为有序分类
typ = typ[0].astype('category')
typ = typ.cat.reorder_categories(['夹雪','小雪', '中雪', '大雪'],ordered=True)
``````

``````#修改为DataFrame，s使用值连接
s = pd.DataFrame(s)
s = s.reset_index()
df_f = df_e.merge(s,on ='date',how='left')
#typ使用索引连接
typ = pd.DataFrame(typ)
df_f = df_f.join(typ,how='outer')
``````
``````df_f = df_f.rename(columns={
'压力_x':'压力','压力_y':'雨量大小',0:'雪量大小'})
``````
Time 站点 压力 date 天气 气温 风向 最高气温 最低气温 温差 是否沙暴 是否有雾 是否有雨 是否有雪 是否晴天 雨量大小 雪量大小
450 2018-01-16 站点4 0.396375 2018-01-16 雨夹雪转阴 4C～-1C 东北风转南风 3-4级转3-4级 4.0 -1.0 5.0 False False True True False 夹雪
451 2018-01-16 站点7 0.209500 2018-01-16 雨夹雪转阴 4C～-1C 东北风转南风 3-4级转3-4级 4.0 -1.0 5.0 False False True True False 夹雪

【END】

思路

【START】

``````#获取风向的数据，并以后两位作为主要风向
p ='(转\w+风|\w+风)'
df_d  = df_f['风向'].str.extract(p)
df_d = pd.DataFrame([str(i)[-2:] for i in df_d[0].to_list()])
``````
``````#转换为4列0-1编码
df_d = pd.get_dummies(df_d[0])
df_d = df_d[['东风','西风','南风','北风']]
#将风向数据拼入df_f，索引连接
df_h = df_f.join(df_d,how='outer')
``````
``````df_h.tail(2)
``````
Time 站点 压力 date 天气 气温 风向 最高气温 最低气温 温差 ... 是否有雾 是否有雨 是否有雪 是否晴天 雨量大小 雪量大小 东风 西风 南风 北风
525598 2019-12-31 23:00:00 站点9 0.201375 2019-12-31 晴转多云 0℃～-5℃ 西风转南风 <3级 0.0 -5.0 5.0 ... False False False True NaN NaN 0 0 1 0
525599 2019-12-31 23:00:00 站点6 0.000000 2019-12-31 晴转多云 0℃～-5℃ 西风转南风 <3级 0.0 -5.0 5.0 ... False False False True NaN NaN 0 0 1 0

2 rows × 21 columns

【END】

3. 对df的水压一列构造如下时序特征

思路

【START】

``````#对df进行改造，新增月和时刻的列值
df = pd.DataFrame(df_h[['Time','date','站点','压力','是否有雨','是否有雪']])
df['month'] = df['Time'].dt.month
df['hour'] = df['Time'].dt.hour
``````
Time date 站点 压力 是否有雨 是否有雪 month hour
0 2018-01-01 2018-01-01 站点4 0.402750 False False 1 0
1 2018-01-01 2018-01-01 站点7 0.214375 False False 1 0
2 2018-01-01 2018-01-01 站点22 0.247000 False False 1 0
3 2018-01-01 2018-01-01 站点21 0.284250 False False 1 0
4 2018-01-01 2018-01-01 站点20 0.292875 False False 1 0
``````#到月到时段的均值计算
df_month = df.groupby(['month','hour','站点'])['压力'].mean()
df_month = df_month.reset_index()
``````
month hour 站点 压力
0 1 0 站点1 0.260095
1 1 0 站点10 0.259512
2 1 0 站点11 0.244476
3 1 0 站点12 0.252960
4 1 0 站点13 0.259923
``````#将到月的数据拼接到df,使用值拼接
df = df.merge(df_month, on=['month','hour','站点'],how='left')
``````
``````df = df.sort_values(by=['站点','hour'],axis=0,ascending=True)
df = df.rename(columns={
'压力_x':'压力','压力_y':'平均压力'})
``````
Time date 站点 压力 是否有雨 是否有雪 month hour 平均压力
21909 2018-01-01 01:00:00 2018-01-01 站点1 0.292000 False False 1 1 0.266966
21939 2018-01-02 01:00:00 2018-01-02 站点1 0.291625 False False 1 1 0.266966
21969 2018-01-03 01:00:00 2018-01-03 站点1 0.296500 False True 1 1 0.266966

【END】

思路

【START】

``````#增加年、周、工作日维度
df['year'] = df['Time'].dt.year
df['week'] = df['Time'].dt.isocalendar().week
df['day_week'] = df['Time'].dt.dayofweek
``````
Time date 站点 压力 是否有雨 是否有雪 month hour 平均压力 year week day_week
9 2018-01-01 2018-01-01 站点1 0.288625 False False 1 0 0.260095 2018 1 0
39 2018-01-02 2018-01-02 站点1 0.286750 False False 1 0 0.260095 2018 1 1
``````#周末的水压均值
df_m = df[df['day_week'].isin([5,6])]
df_m2 = df_m.groupby(['站点','year','month','week'])['压力'].mean()
df_m2 = df_m2.reset_index()
df_m2 = df_m2.rename(columns={
'压力':'周末平均压力'})
``````

0 站点1 2018 1 1 0.251711
1 站点1 2018 1 2 0.248945
``````#工作日的水压均值
df_w = df[df['day_week'].isin([0,1,2,3,4])]
df_w2 = df_w.groupby(['站点','year','month','week'])['压力'].mean()
df_w2 = df_w2.reset_index()
df_w2 = df_w2.rename(columns={
'压力':'工作日平均压力'})
``````

0 站点1 2018 1 1 0.253222
1 站点1 2018 1 2 0.252750
``````#拼接数据
df = df.merge(df_m2, on=['站点','year','month','week'],how='left')
df = df.merge(df_w2, on=['站点','year','month','week'],how='left')
``````
``````#做差值
df['周末与工作日压力差值'] = df['周末平均压力'] - df['工作日平均压力']
df.tail(2)
``````
Time date 站点 压力 是否有雨 是否有雪 month hour 平均压力 year week day_week 周末平均压力 工作日平均压力 周末与工作日压力差值
525598 2019-12-30 23:00:00 2019-12-30 站点9 0.225375 False False 12 23 0.247349 2019 1 0 NaN 0.218828 NaN
525599 2019-12-31 23:00:00 2019-12-31 站点9 0.201375 False False 12 23 0.247349 2019 1 1 NaN 0.218828 NaN

【END】

思路

【START】

``````s = df.copy()
#得到到单日的均值
f = pd.DataFrame(s.groupby(['date','站点'])['压力'].mean())
f = f.reset_index()
#创建站点的序列，以便下面的循环
z = pd.Series(s['站点'].unique())
``````
``````for i in z:
#给定到站点
s = f[f['站点']==i]
#要使用rolling，所以字段仅为日期和压力
s = s[['date','压力']]
#对date进行一个排序
s = s.sort_values(by='date')
#设置索引
s1 = s.set_index('date')
#rolling取7天均值
r = s1.rolling(window=7)
r1 = r.mean()
#将站点的值拼入r1中
m = pd.DataFrame([i]*r1.shape[0],index=s['date'].to_list(),columns=['站点'])
n = pd.concat([r1,m],1)
#得到最终结果
result = pd.concat([result,n])
result[result['站点']=='站点2']
``````

2018-01-01 NaN 站点2
2018-01-02 NaN 站点2
2018-01-03 NaN 站点2
2018-01-04 NaN 站点2
2018-01-05 NaN 站点2
... ... ...
2019-12-27 0.335159 站点2
2019-12-28 0.335098 站点2
2019-12-29 0.334743 站点2
2019-12-30 0.335152 站点2
2019-12-31 0.335009 站点2

2920 rows × 2 columns

【END】

思路

【START】

``````s = df.copy()
#得到到单日的均值
f = s[['Time','hour','站点','压力']]
#创建站点的序列，以便下面的循环
z = pd.Series(s['站点'].unique())
t = pd.Series(s['hour'].unique())
``````
``````for i in z:
for j in t:
#给定到站点
s = f[f['站点']==i]
#要使用rolling，所以字段仅为日期和压力
s = s[s['hour']==j]
s = s[['Time','压力']]
#对date进行一个排序
s = s.sort_values(by='Time')
#设置索引
s1 = s.set_index('Time')
#rolling取7天均值
r = s1.rolling(window=7)
r1 = r.mean()
#将站点的值拼入r1中
m = pd.DataFrame([i]*r1.shape[0],index=s['Time'].to_list(),columns=['站点'])
n = pd.concat([r1,m],1)
#得到最终结果
result = pd.concat([result,n])
result[result['站点']=='站点2']
``````

2018-01-01 00:00:00 NaN 站点2
2018-01-02 00:00:00 NaN 站点2
2018-01-03 00:00:00 NaN 站点2
2018-01-04 00:00:00 NaN 站点2
2018-01-05 00:00:00 NaN 站点2
... ... ...
2019-12-27 23:00:00 0.338964 站点2
2019-12-28 23:00:00 0.339286 站点2
2019-12-29 23:00:00 0.339982 站点2
2019-12-30 23:00:00 0.341054 站点2
2019-12-31 23:00:00 0.339714 站点2

20440 rows × 2 columns

思路

【START】

``````#找到水压的最高点，先通过groupby找到最高点的值，然后再通过merge的inner找到最高点的时段
df5 = df_e.copy()
df1 = df5.groupby(['站点','date'])['压力'].max()
#这里出现了一个问题，最大值和最小值存在多条记录的情况，所以选择在对Time取最大值
df_n = df5.merge(df1,on=['站点','date','压力'],how='inner')
df_n = pd.DataFrame(df_n.groupby(['站点','date'])['Time'].max())
df_max = df_n.reset_index()
df_max = df_max.rename(columns={
'Time':'max_time'})
``````
``````#找到水压的最高点，先通过groupby找到最高点的值，然后再通过merge的inner找到最高点的时段
df2 = df5.groupby(['站点','date'])['压力'].min()
df_n = df5.merge(df2,on=['站点','date','压力'],how='inner')
#这里最小值存在多值的问题选择最小值
df_n = pd.DataFrame(df_n.groupby(['站点','date'])['Time'].min())
df_min = df_n.reset_index()
df_min = df_min.rename(columns={
'Time':'min_time'})
``````
``````#通过date和站点将最大值和最小值拼接
df_f = df_max.merge(df_min, on=['date','站点'],how='outer')
df_f['time_diff'] = df_f['max_time'] -df_f['min_time']
df_f.sort_values(by=['date'])
df_f = df_f[['date','站点','time_diff']]
``````
date 站点 time_diff
0 2018-01-01 站点1 -1 days +18:00:00
1 2018-01-02 站点1 -1 days +18:00:00

【END】