旧金山犯罪类型
本案例大纲:
1、了解题目背景
2、特征工程
3、模型选择
4、基于R实现模型
1、了解背景
洛杉矶警方给了我们十多年的犯罪记录数据,我们需要根据这些数据预测犯罪类型,警方知道犯罪类型以后,可以更好地应对突发事件,针对性地采取措施。本次案例的主要目的有如下几点:
(1)
预测
test
数据集的犯罪类别
(2) 对犯罪数据进行可视化
本案例的数据字典如下:
Dates | 日期 | 犯罪事件的时间戳 | 备注 |
Category | 类别 | 犯罪事件类别 | 仅在train.csv里有 |
Descript | 描述 | 犯罪事件的详细描述 | 仅在train.csv里有 |
DayOfWeek | 星期几 | 星期几 | |
PdDistrict | 警察局区域名称 | 警察局区域名称 | |
Resolution | 解决方式 | 犯罪事件如何解决 | 仅在train.csv里有 |
Address | 地址 | 犯罪事件的大致街道地址 | |
X | 经度 | 经度 | |
Y | 纬度 | 纬度 |
2、特征工程
(1)提取事件发生的时间的年份
(2)提取事件发生的时间的月份
(3)提取事件发生的时间的小时
(4)提取事件发生的时间的地理位置
3、模型选择
因变量为连续型数据的回归为线性回归,因变量为二分类变量的回归为Logistic回归,因变量服从泊松分布的回归为泊松回归,这里选择Logistic回归。但源数据是多分类问题,一共有39个分类,需要将多分类问题转为二分类问题,方法是创建一个新的数据框命名为response,行数与源数据相同,并将源数据的类别变量赋值到response的新列cat列,且将这39个类变成response的39个新列,每一列列名为类名,与列名相同的那一行,将该行赋值为1。以下展示部分response数据框的数据:
cat ARSON ASSAULT BAD CHECKS BRIBERY BURGLARY DISORDERLY CONDUCT 1 WARRANTS 0 0 0 0 0 0 2 OTHER OFFENSES 0 0 0 0 0 0 3 OTHER OFFENSES 0 0 0 0 0 0 4 LARCENY/THEFT 0 0 0 0 0 0 5 LARCENY/THEFT 0 0 0 0 0 0 6 LARCENY/THEFT 0 0 0 0 0 0 DRIVING UNDER THE INFLUENCE DRUG/NARCOTIC DRUNKENNESS EMBEZZLEMENT EXTORTION FAMILY OFFENSES 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 4 0 0 0 0 0 0 5 0 0 0 0 0 0 6 0 0 0 0 0 0 FORGERY/COUNTERFEITING FRAUD GAMBLING KIDNAPPING LARCENY/THEFT LIQUOR LAWS LOITERING 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 4 0 0 0 0 1 0 0 5 0 0 0 0 1 0 0 6 0 0 0 0 1 0 0 MISSING PERSON NON-CRIMINAL OTHER OFFENSES PORNOGRAPHY/OBSCENE MAT PROSTITUTION 1 0 0 0 0 0 2 0 0 1 0 0 3 0 0 1 0 0 4 0 0 0 0 0 5 0 0 0 0 0 6 0 0 0 0 0 RECOVERED VEHICLE ROBBERY RUNAWAY SECONDARY CODES SEX OFFENSES FORCIBLE 1 0 0 0 0 0 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 5 0 0 0 0 0 6 0 0 0 0 0 SEX OFFENSES NON FORCIBLE STOLEN PROPERTY SUICIDE SUSPICIOUS OCC TREA TRESPASS VANDALISM 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 VEHICLE THEFT WARRANTS WEAPON LAWS 1 0 1 0 2 0 0 0 3 0 0 0 4 0 0 0 5 0 0 0 6 0 0 0
这样就变成了二分类问题,每一列都是一个二分类问题,每一列做一次Logistic回归。
4、R语言实现
train<-read.csv('D:/R语言kaggle案例实战/Kaggle第三节课/train.csv')
test<-read.csv('D:/R语言kaggle案例实战/Kaggle第三节课/test.csv')
library(MASS)
library(readr)
library(caret)
library(lubridate)
#以下为特征提取,把该部分写成函数形式。
make_feature<-function(df){
dates1<-strptime(as.character(df$Dates),"%Y-%m-%d %H:%M:%s")#将字符串形式的时间转为字符形式。
df$year<-dates1$year
df$Months<-dates1$mon
df$Hour<-hour(dates1)
df$Loc<-as.factor(paste(round(df$X,2),round(df$Y,2),sep=" "))#合并经纬度
return(df)
}
train<-make_feature(train)#训练集数据特征提取
test<-make_feature(test)#测试集数据特征提取
logistic_regression<-function(train,test){
submission<-data.frame(Id=test$Id)
response<-data.frame(cat=train$Category)#将犯罪类型作为response数据框的第一列
crime<-as.character(unique(train$Category))# 去重犯罪类型
crime<-sort(crime)#排序
for(i in crime){ #这个循环的目的是将多分类问题转为二分类问题,即将每一个类别作为一列,类名就是列名。
response[,i]<-0 #初始化每一类的值为0
response[which(response$cat==i),i]<-1#将属于某类的那行的值重新赋值为1,这样每一列的类别与列名相同的值为1,否则为0,这样就转换成了二分类问题,每一列都是一个二分类问题。
fit<-glm(response[,i]~PdDistrict+DayOfWeek+year+Months+Hour+X:Y,data=train,family=binomial)#防止属于同一纬度类别过多,所以用x:y
pre<-predict(fit,test,type="response")#type为response表示类别的概率。
submission[,i]<-pred
}
return(submission)
}
submission_final<-logistic_regression(train,test)