DAY7:Kaggle-San Francisco Crime Classification(下)

  • 资料视觉化

这边我们会用到seaborn来做一下简单的资料视觉化。

import seaborn as sns

sns.set()

我们先来看看犯罪类型的数量,由於种类较多,我就先截部分。

data = train.groupby('Category').count()
data = data['Dates'].sort_values(ascending=False)
print(data)

接下来我们将它视觉化,这样就可以很清楚的看到各种犯罪类型的占比。

plt.figure(figsize=(20, 12))
ax = sns.barplot((data.values / data.values.sum())*100,data.index)
plt.title('Count by Category', fontdict={'fontsize': 21})
plt.xlabel('Percentage')

再来看看在几点钟的时候比较有犯罪发生,类型是甚麽呢?

fig, ax = plt.subplots(figsize=(24,16))
fig.suptitle('Num. Incidents / Hour (Category)')
for category in train['Category'].unique():
    #print(category)
    data = train[train['Category'] == category].groupby('Hour')
    a = data['Hour'].count()
    ax.plot(a.index, data['Hour'].count(), label=category)
plt.legend()
plt.show()

可以很清楚看到在傍晚约18-19点犯罪是最多的。

再来我们看看星期几跟犯罪的相关性。

fig, ax = plt.subplots(figsize=(24,16))

def plotbycol(df, col, title):
    fig.suptitle(title)
    for category in df['Category'].unique():
        #print(category)
        data = df[df['Category'] == category].groupby(col)
        a = data[col].count()
        ax.plot(a.index, data[col].count(), label=category)
    
    plt.legend()
    plt.show()
    
plotbycol(train, 'DayOfWeek', "Incidents by Week")

这看起来没有说星期几特别容易有犯罪。


  • 资料前处理

接续昨天的资料前处理,今天还有一部分的资料处理没做完,我们要先将类别变数变成虚拟变数之後,才能丢进模型建模。

变成虚拟变数的常见方法有两种:
  1. One hot encoding:把要处理的特徵(假设此特徵有N个类别),新增成N栏,每栏只会有两个数值,0或1,由0为非,1为是,来表示原本的特徵是属於哪个类别。
  2. label encoding:把要处理的特徵(假设此特徵有N个类别),把其中的类别转换成0~(N-1)的数字,分别去代表其中的类别。

这里我们用到One hot encoding,我们先将我们要预测的应变数Y拉出来。

y=pd.get_dummies(train['Category'])
print(y.head(5))

如下图,可以看见一栏被分成39栏,分别用0或1代表是否属於那个类别。

在train和test部分,我们还有两个变数要做转换,"PdDistrict"以及"Block",另外我们把特徵"Year"也删除,test的"Id"也要删除。

# 处理"PdDistrict"
dummies_train=pd.get_dummies(train['PdDistrict'])
dummies_test=pd.get_dummies(test['PdDistrict'])

# 将原本的"PdDistrict"特徵删除
train=pd.concat([train,dummies_train],axis=1)
train.drop('PdDistrict',inplace=True,axis=1)

test=pd.concat([test,dummies_test],axis=1)
test.drop('PdDistrict',inplace=True,axis=1)

# 处理"Block"
dummies_train=pd.get_dummies(train['Block'])
dummies_test=pd.get_dummies(test['Block'])

# 将原本的"Block"特徵删除
train=pd.concat([train,dummies_train],axis=1)
train.drop('Block',inplace=True,axis=1)

test=pd.concat([test,dummies_test],axis=1)
test.drop('Block',inplace=True,axis=1)

# 另外这边想把Year这个变数也删除掉,跟删除日期的理由一样
X=train.drop(['Category','Year'],axis=1)
test.drop('Year',inplace=True,axis=1)

# test的Id也是,先将他删除
test_no_id = test.drop('Id',axis=1)

print("X资料集")
print(X.head(5))
print("=====================================================================================")
print("test资料集")
print(test_no_id.head(5))

这是我们处理完,X资料集是我们要丢入模型训练的资料,test则是模型训练出来,要丢进去预测的资料。

再来我们用tensorflow架一个神经网路当作我们的模型。

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)
print(X_train.shape,y_train.shape)
print(X_test.shape,y_test.shape)

这边我们一个神经网路模型,隐藏层的激活函数都用relu,输出层我们用softmax。另外我们要给model一个优化器,这边我选择用adam,它收敛较快,loss_function选择crossentropy。

from tensorflow import keras
from keras.layers import Dense,Dropout
from keras.models import Sequential

model=Sequential()
model.add(Dense(128,input_shape=(X.shape[1],)))
model.add(Dense(128,activation='relu'))
model.add(Dense(128,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(39,activation='softmax'))
model.summary()

model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])        
train=model.fit(X_train,y_train, 
         batch_size=512,
         epochs=100,
         verbose=2,
         validation_data=(X_test,y_test))      

接下来就丢进去模型训练啦!!

train=model.fit(X_train,y_train, batch_size=512,epochs=100,verbose=2,validation_data=(X_test,y_test))

恩...准确度好像是满糟糕的,但多分类,觉得先上传试试看,先能做出来,再来调整修改!

拿练好的模型来预测罗!!

pred=model.predict(test_no_id)

m = np.max(pred, axis=1).reshape(-1, 1)
predicted = np.array((pred == m), dtype='int64')
print(predicted)

这是我产出的样子,总共有39个类别,属於那个类别就为1,否则为0。

然後就产出CSV上传啦

sample=pd.read_csv(r'C:\Users\Frank\Desktop\kaggledata\sf-crime\sampleSubmission.csv')
col_names=list(sample.columns)
col_names.remove('Id')
submission = pd.DataFrame()
submission['Id']=test['Id']
for i, entry in enumerate(col_names):
    submission[entry] = predicted[:,i]

submission.to_csv(r'./submission_crime.csv', index=False)

这个分数是越低越好,它是用loss去评分的,不过对我们来说分数不重要,重点是你练习会了整个流程,从拿到资料,资料前处理,再到产出模型,产出你的预测。会了之後再回头看哪边可以调整试试看,让分数变得更好看。

  • 今日小结

这是我们碰到第一个多分类的问题,其实流程来说都差不多,那多分类的模型就要选择一下,例如罗吉斯回归就不是用在多分类,Adaboost、SVC也是,模型的部分就可以选择一下,我也有试着用集成学习来跑,但因为跑太久,还没出来,等出来结果如果有比较好再来跟大家分享罗!!
明天要来试着玩看看图像辨识的部分,因为工作有用到验证码辨识,我就把它纪录下来,当作我的学习记录罗~


<<:  [Day22]The 3n + 1 problem

>>:  #6-无限文字Logo跑马灯 (不用JS! CSS Animation)

就先在这边帮他上了一个主题了 Day1

今天是自己开始铁人赛的第一天,目标其实很简单,想要把之前学到的,之前没学到的 全部整合整理成一个作品...

何谓工程(Engineering)?

Image Credit: City of Gastonia 工程是指运用知识和技能来理解和管理利...

[Linux] 让程序在背景执行

订阅patreon即可看到更多文章 https://www.patreon.com/wade3c ...

Gitlab EE 授权获取工具

示例环境: debian10 Ruby Version ≥2.5 生成授权需要安装依赖: ## 确认...

Day10 我的工作环境

作业系统 前九天的内容大致上是我在Day1提到的扫盲课程学到的东西,当时我使用的是一台Windows...