BigData——PYspark案例
一.选题
1.1 背景
从 1934 年到 1963 年,旧金山因将一些世界上最臭名昭著的罪犯关押在无法逃脱的岛而臭名昭著恶魔 。
今天,这座城市以其科技场景而闻名,而不是它的犯罪历史。但是,随着财富不平等的加剧、住房短缺以及乘坐 BART 上班的昂贵数字玩具的激增,海湾边的城市并不缺乏犯罪。
从 Sunset 到 SOMA,从 Marina 到 Excelsior,本次比赛的数据集提供了旧金山所有社区近 12 年的犯罪报告。给定时间、地点和一定的描述,您必须预测发生的犯罪类别。
1.2 主要工作
为了解决上述提出的问题,我们从kaggle网站上San Francisco Crime Classification比赛中下载了相关数据集。从数据集介绍、导入,进行数据探索性分析和数据可视化,数据预处理,到构建多种分类预测模型,在测试集上全方位评估模型分类性能。对机器学习模型进行可解释性分析,从各个角度打破模型黑箱子,解释特征重要度,解释样本哪些特征导致对模型预测结果造成影响,从海量数据中挖掘相似性,让我们对模型充分了解、信任。
二. 准备数据
2.1数据集整体介绍
该数据集包含源自 SFPD 犯罪事件报告系统的事件。 数据范围从 1/1/2003 到 5/13/2015。 训练集和测试集每周轮换一次,即第 1、3、5、7...周属于测试集,第 2、4、6、8 周属于训练集。数据集整体介绍如下表所示:
数据集 | 数据类型 | 属性数 | 实例数 | 值缺失 | 相关任务 |
---|---|---|---|---|---|
SFPD | 字符类型 | 9 | 878049 | 否 | 分类预测 |
数据集来源:https://www.kaggle.com/c/sf-crime/data
2.2数据集属性介绍
如上表所示,该数据集总共有878049条记录数据,9个属性列,每个属性列均无缺失值,数据集中的数据类型均为字符类型,本实验主要用这个数据集进行数据分析和可视化,主要用到的机器学习中的分类算法。
本数据集中共有9个属性列,其中有8个特征列和1个标签列,关于各属性列的详细介绍如下表所示:
Attribute | Explain | Type |
---|---|---|
Dates | 日期 | 字符型 |
Category | 类别 | 字符型 |
Descript | 描述 | 字符型 |
DayOfWeek | 星期几 | 字符型 |
PdDistrict | 辖区警察局 | 字符型 |
Resolution | 解决方案 | 字符型 |
Address | 发生地点 | 字符型 |
X | 经度 | 字符型 |
Y | 维度 | 字符型 |
三.上传数据
Step1:在网站上把数据下载到本地。
Step2:利用Xftp把本地数据集放到集群的master节点上,目录为/bigdata/pyspark/data
Step3:在hdfs文件中创建文件夹/pyspark
# hadoop fs -mkdir /pyspark |
---|
# hadoop fs -ls / |
Step4:上传数据到指定hdfs文件夹
# hadoop fs -put /bigdata/pyspark/data/train.csv /pyspark |
---|
# hadoop fs -ls /pyspark |
四.数据预处理和环境准备
集群配置简介:
三台虚拟机CentOS6.5
Master 192.168.174.101
Node1 192.168.174.102
Node2 192.168.174.103
JDK 版本 1.8.0 安装路径 /bigdata/jdk1.8.0
Hadoop 版本2.6.0 安装路径 /bigdata/hadoop-2.6.0
Zookeeper 版本 3.4.6 安装路径 /bigdata/zookeeper-3.4.6
Hbase 版本 1.0.1.1 安装路径 /bigdata/hbase-1.0.1.1
MySQL 版本 5.1.73 安装路径 /usr/bin/mysql
Hive 版本 1.2.1 安装路径 /bigdata/hive-1.2.1
Spark 版本 2.4.8 安装路径 /bigdata/spark-2.4.8
Scala 版本 2.11.8 安装路径 /bigdata/scala-2.11.8
Anaconda3 版本5.0.0 安装路径 /root/anaconda3
Python 版本3.6.2 Anaconda自带
Sqoop 版本 1.4.7 安装路径 /bigdata/sqoop-1.4.7
我们需要查看数据信息,并对数据经行清洗。为我们接下来的可视化分析和数据建模提供良好的数据源,方便处理。
Step1:加载数据并查看数据属性
Step2: 查看部分数据
Step3:查看是否存在空置或异常值
发现没有明显异常数据和空值。
https://gitee.com/xiang976young/note/raw/master/img/
五.数据导入
5.1 创建Hive数据库和数据表
进入hive shell环境,创建crime数据库和log外部表(外部表可以在修改表数据的同时不伤害本身原始数据,为数据做保护),并载入hdfs中的数据。
hive> create database crime; |
---|
hive> use crime; |
hive> create external table log( Dates string, Category string, Descript String, PdDistrict string, Resolution string, Address String, X string, Y string )row format delimited fields terminate by ‘,’ stored as textfile location ‘/spark’; |
hive> select * from log limit 10; |
(数据一开始放在/spark文件夹下,后来有创建了新的/pyspark 数据一致)
为外部表log创建内部表inner_log
hive> create table inner_log( Dates string, Category string, Descript String, DayOfWeek string ,PdDistrict string, Resolution string, Address String, X string, Y string) comment 'Welcome to XMU dblab! Now create inner table inner_log ' row format delimited fields terminate by ‘,’ stored as textfile; |
---|
hive> select * from log limit 10; |
5.2 创建MySQL数据库和数据表
因为sqoop在抓取数据的时候,会把所有的数据都抓成string类型,所以在创建表的时候,要注意属性的类型。同时也要查看当前数据库下是否支持utf-8编码。以免出现中文乱码的情况。
mysql> create database crime; |
---|
mysql > use crime; |
mysql > show variables like "char%"; |
mysql > CREATE TABLE crime .log (Dates varchar(255), Category varchar(255),Descript varchar(255),DayOfWeek varchar(20), PdDistrict varchar(255), Resolution varchar(255),Address varchar(255),X varchar(255),Y varchar(255)) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
mysql > select * from log limit 10; |
5.3 利用Sqoop从Hive中导出数据到MySQL
在利用sqoop处理数据的时候要注意,如果hive表中存在属性为数值行的none值,要注意切换为字符NULL,不然会报错。
# sqoop export --connect jdbc:mysql://192.168.174.101:3306/crime --username root --password 123456 --table log --export-dir '/user/hive/wavehouse/crime.db/log' --fields-terminated-by ',' -m 1; |
---|
mysql > select * from crime.log limit 10; |
5.4 利用Sqoop从MySQL中导出数据到Hbase
由于该数据集并没有主键的存在,并不能很好的标记各个记录。所以这里需要给mysql表添加一个id的主键,以标记各个记录。
**mysql > alter table log add id int** |
---|
mysql > alter table node_table change id id int not null auto_increment primary key; mysql > select * from log limit 10; |
创建hbase表:
**hbase(main):003:0> create ”log”,”info”** |
---|
**hbase(main):004:0> list** |
利用sqoop从mysql导入数据到hbase:
**# sqoop import --connect jdbc:mysql://192.168.174.101:3306/crime --username root --password 123456 --table log --columns "dates,category,descript,dayofweek,pddistrict,resolution,address,x,y,id" --column-family "info" --hbase-create-table --hbase-table "log" --hbase-row-key "id" --num-mappers 1 --split-by id** |
---|
**hbase(main):001:0> scan ‘log’** |
(scan 查询数目太多,没有办法截下来)
5.5 Hive与Hbase的数据映射
将HBase数据仓库中log数据映射到Hive数据库的外部表hive_log中
**hive> create external table hive_log(Dates string, Category string, Descript String, DayOfWeek string ,PdDistrict string, Resolution string, Address String, X string, Y string,id int )STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = "info:dates,info:category,info:descript,info:dayofweek,info:pddistrict,info:resolution,info:address,info:x,info:y,:key") TBLPROPERTIES ("hbase.table.name" = "log");** |
---|
**hive> show tables;** |
**hive> desc hive_log;** |
至此,数据仓库、两个数据库之间的数据已经全部加载完成。
六.Hive数据分析
6.1 分析犯罪类型发生的次数最多的10个
hive> select category,count(*) as category_count from log group by category order by category_count desc limit 10; |
---|
6.2 分析发生犯罪最多的20个街区
hive> select pddistrict,count(*) as pddistrict_count from log group by pddistrict order by pddistrict_count desc limit 20; |
---|
6.3 分析每个星期内发证犯罪的情况
hive> select dayofweek,count(*) from log group by dayofweek ; |
---|
七.Spark数据分析与可视化
这里的Spark的编程语言选择的Python,运行的平台是Jupyter
7.1 Spark数据可视化
7.1.1 各犯罪类型数量统计
plt.rcParams['figure.figsize']=(20,9) plt.style.use('dark_background') sns.countplot(dataset['Category'],palette='gnuplot') plt.title('Major Crimes in Sanfrancisco',fontweight=30,fontsize=20) plt.xticks(rotation=90) plt.show()
由图可以明显的看出来,在SanFrancisco LARCENY/THEFT和OTHER OFFENSES这两类犯罪是最多的
7.1.2 各个街区的犯罪对比示意图
df = pd.crosstab(dataset['Category'],dataset['PdDistrict'])
color = plt.cm.Greys(np.linspace(0, 1, 10))
df.div(df.sum(1).astype(float), axis = 0).plot.bar(stacked = True, color = color, figsize = (18, 12))
plt.title('District vs Category of Crime', fontweight = 30, fontsize = 20)
plt.xticks(rotation = 90)
plt.show()
有图可以观察到,地区之间差异还是挺大的,southern地区犯罪率较高,治安最好的是Richmond
7.1.3 按时间对犯罪进行划分并分析
dataset['year'] = dataset['Dates'].dt.year
dataset['month'] = dataset['Dates'].dt.month
dataset['day'] = dataset['Dates'].dt.day dataset['hour'] = dataset['Dates'].dt.hour
plt.figure(figsize=(8,19))
plt.style.use('fivethirtyeight')
year_group = dataset.groupby('year').size()
plt.subplot(311)
plt.plot(year_group.index[:-1],year_group[:-1],'ks-') plt.xlabel('year')
month_group = dataset.groupby('month').size()
plt.subplot(312)
plt.plot(month_group,'ks-')
plt.xlabel('month')
day_group = dataset.groupby('day').size()
plt.subplot(313)
plt.plot(day_group,'ks-')
plt.xlabel('day')
plt.show()
从上图可知,在2011年前SF的犯罪数基本上呈递减趋势,2011后数量激增,案件高发期是在一年中的5月和10月,在每个月的月初会有涨幅。
week_group = dataset.groupby(['DayOfWeek','hour']).size()
#多重分组
week_group = week_group.unstack()
#对分组后的多重索引转为xy索引
week_group.T.plot(figsize=(12,8))#行列互换后画
plt.xlabel('hour of day',size=15)
plt.ylabel('Number of crimes',size=15)
plt.show()
·
可以看出,案件高发时间是在12点和18点左右,凌晨后数量会显著减少,在周五周六的晚上8点后案件发生率会比平时要高。
7.1.4 高发案件的时间结合地点的分析
cate_group = dataset.groupby(by='Category').size()
top6 = list(cate_group.index[:6])
tmp = dataset[dataset['Category'].isin(top6)]
tmp_group = tmp.groupby(['Category','hour']).size()
tmp_group = tmp_group.unstack()
tmp_group.T.plot(figsize=(12,6),style='o-')
plt.show()
时间上与上述分析是一致的,对于偷盗类案件在12、18点发生率更高;assault类案件在晚上6点后没有下降趋势。
tmp2 = tmp.groupby(['Category','PdDistrict']).size() tmp2.unstack().T.plot(kind='bar',figsize=(12,6),rot=45) plt.show()
从上图可知,犯罪率最高的Southern地区,偷窃类、暴力冲突类案件数量最多,车辆失窃类案件较少,猜测可能属于贫困地区,治安很好的地区Park,Richmond中,毒品、人身攻击类案件比例明显较少.
tmp3 = tmp.groupby(['Category','DayOfWeek']).size()
tmp3 = tmp3.unstack()
for i in range(6):
tmp3.iloc[i] = tmp3.iloc[i]/tmp3.sum(axis=1)[i] print(tmp3)
tmp3.T.plot(figsize=(12,6),style='o-')
plt.xlabel("weekday",size=20)
#plt.axes.set_xticks([])
plt.xticks([0,1,2,3,4,5,6],['Mon','Tue','Wed','Thur','Fri','Sat','Sun'])
plt.show()
趋势不太一样的是BAD CHECK类案件,在周三发生最多,周末有急剧下降的趋势;其余多数案件,除了other offenses外,都在周五周六有所增多。
mon_g = tmp.groupby(['Category','month']).size()
mon_g = mon_g.unstack()
for i in range(6):
mon_g.iloc[i] = mon_g.iloc[i]/mon_g.sum(axis=1)[i] mon_g.T.plot(figsize=(12,6),style='o-')
plt.show()
分类变化趋势与总体基本一致,2-6月和8-12月是案件高发期,1-2月badcheck案发率较低。
7.1.5 高发案件的时间趋势分析
ddf = tmp.groupby(['Category',pd.Grouper('Dates')]).size() ddf = ddf.unstack().fillna(0)
ddf = ddf.T
df2 = ddf.resample('m',how='sum')#按月求和
plt.style.use('dark_background')
moav = df2.rolling(12).mean()#每12个月统计平均,相当于加了个窗
i = 1
for cat in df2.columns:
plt.figure(figsize=(12,15))
ax = plt.subplot(6,1,i)
plt.plot(df2.index,df2[cat])
plt.plot(df2.index,moav[cat])
plt.title(cat)
i+=1
df2.plot()
可见,不同种类的案件随时间是有不同变化的,如assault在15年后急剧下降,可能有专项整治等活动。
7.2 Spark数据分析
7.2.1 Spark.Mlib介绍
Spark数据分析建模主要利用的是Spark.Mlib下的机器学习进行分类、预测、回归问题。Mlib其实就是将数据以RDD的形式进行表示,在分布式数据集上调用各种算法。
Mlib的使用方法:
MLlib中包含能够在集群上运行良好的并行算法,如kmeans、分布式RF、交替最小二乘等,这能够让MLib中的每个算法都能够适用于大规模数据集
也可以将同一算法的不同参数列表通过parallelize(),在不同节点上运行,最终找到性能最好的一组参数,这可以节省小规模数据集上参数选择的时间。
Mlib中的数据类型:
Vector:在mllib.linalg.vectors中,既支持稠密向量,也支持稀疏向量
LabeledPoint:在mllib.regression中,用于监督学习算法中,表示带有标签的数据点
Rating:在mllib.recommendation中,用于产品推荐,表示用户对一个产品的打分
各种Label类:每个Model都是训练算法的结果,可以用train进行训练,用predict进行预测
7.2.2 基于Describe属性分词处理的数据分析
流程和scikit-learn版本的很相似,包含3个步骤:
1.regexTokenizer: 利用正则切分单词
2.stopwordsRemover: 移除停用词
3.countVectors: 构建词频向量
RegexTokenizer:基于正则的方式进行文档切分成单词组 inputCol: 输入字段;outputCol: 输出字段;pattern: 匹配模式,根据匹配到的内容切分单词。
CountVectorizer:构建词频向量;covabSize: 限制的词频数;minDF:如果是float,则表示出现的百分比小于minDF,不会被当做关键词
StringIndexer将一列字符串label编码为一列索引号,根据label出现的频率排序,最频繁出现的label的index为0
该例子中,label会被编码成从0-32的整数,最频繁的label被编码成0
Pipeline是基于DataFrame的高层API,可以方便用户构建和调试机器学习流水线,可以使得多个机器学习算法顺序执行,达到高效的数据处理的目的。
以词频作为特征,利用逻辑回归进行分类 LR用于监督式分类问题,可以使用SGD等方法对LR进行训练, clearThreshold之后,LR会输出原始概率,也可以设置概率阈值,直接输出分类结果 |
---|
drop_list = ['Dates', 'DayOfWeek', 'PdDistrict', 'Resolution', 'Address', 'X', 'Y'] data = data.select([column for column in data.columns if column not in drop_list]) from pyspark.ml.feature import RegexTokenizer, StopWordsRemover, CountVectorizer from pyspark.ml.classification import LogisticRegression # regular expression tokenizer regexTokenizer = RegexTokenizer(inputCol="Descript", outputCol="words", pattern="\W") # stop words add_stopwords = ["http","https","amp","rt","t","c","the"] stopwordsRemover = StopWordsRemover(inputCol="words", outputCol="filtered").setStopWords(add_stopwords) # bag of words count countVectors = CountVectorizer(inputCol="filtered", outputCol="features",vocabSize=10000, minDF=5) |
label_stringIdx = StringIndexer(inputCol = "Category", outputCol = "label") pipeline = Pipeline(stages=[regexTokenizer, stopwordsRemover, countVectors, label_stringIdx]) # Fit the pipeline to training documents. pipelineFit = pipeline.fit(data) dataset = pipelineFit.transform(data) (trainingData, testData) = dataset.randomSplit([0.7, 0.3], seed = 100) lr = LogisticRegression(maxIter=20, regParam=0.3, elasticNetParam=0) lrModel = lr.fit(trainingData) predictions = lrModel.transform(testData) predictions.filter(predictions['prediction'] == 0) \ .select("Descript","Category","probability","label","prediction") \ .orderBy("probability", ascending=False) \ .show(n = 10, truncate = 30) evaluator = MulticlassClassificationEvaluator(predictionCol="prediction") evaluator.evaluate(predictions) |
以TF-ID作为特征,利用逻辑回归进行分类 TFIDF是一种从文本文档生成特征向量的简单方法,文档中的词有2个统计值:TF与IDF,TF指的是每个词咋文档中出现的次数,IDF用于衡量一个词在整个文档语料库中出现的(逆)频繁程度 HashingTF用于计算TF,IDF用于IDF,hashingTF用的是哈希的方法,生成稀疏向量 |
from pyspark.ml.feature import HashingTF, IDF hashingTF = HashingTF(inputCol="filtered", outputCol="rawFeatures", numFeatures=10000) idf = IDF(inputCol="rawFeatures", outputCol="features", minDocFreq=5) #minDocFreq: remove sparse terms pipeline = Pipeline(stages=[regexTokenizer, stopwordsRemover, hashingTF, idf, label_stringIdx]) pipelineFit = pipeline.fit(data) dataset = pipelineFit.transform(data) lr = LogisticRegression(maxIter=20, regParam=0.3, elasticNetParam=0) lrModel = lr.fit(trainingData) predictions = lrModel.transform(testData) predictions.filter(predictions['prediction'] == 0) \ .select("Descript","Category","probability","label","prediction") \ .orderBy("probability", ascending=False) \ .show(n = 10, truncate = 30) evaluator = MulticlassClassificationEvaluator(predictionCol="prediction") evaluator.evaluate(predictions) |
交叉验证 用交叉验证来优化参数,这里针对基于词频特征的逻辑回归模型进行优化 |
#交叉验证 from pyspark.ml import Pipeline pipelinec = Pipeline(stages=[regexTokenizer, stopwordsRemover, countVectors, label_stringIdx]) pipelineFit = pipelinec.fit(data) dataset = pipelineFit.transform(data) (trainingData, testData) = dataset.randomSplit([0.7, 0.3], seed = 100) lr = LogisticRegression(maxIter=20, regParam=0.3, elasticNetParam=0) from pyspark.ml.tuning import ParamGridBuilder, CrossValidator # Create ParamGrid for Cross Validation paramGrid = (ParamGridBuilder() .addGrid(lr.regParam, [0.1, 0.3, 0.5]) # regularization parameter .addGrid(lr.elasticNetParam, [0.0, 0.1, 0.2]) # Elastic Net Parameter (Ridge = 0) # .addGrid(model.maxIter, [10, 20, 50]) #Number of iterations # .addGrid(idf.numFeatures, [10, 100, 1000]) # Number of features .build()) from pyspark.ml.evaluation import MulticlassClassificationEvaluator evaluator = MulticlassClassificationEvaluator(predictionCol="prediction") # Create 5-fold CrossValidator cv = CrossValidator(estimator=lr, \ estimatorParamMaps=paramGrid, \ evaluator=evaluator, \ numFolds=5) cvModel = cv.fit(trainingData) predictions = cvModel.transform(testData) # Evaluate best model evaluator.evaluate(predictions) |
朴素贝叶斯 |
from pyspark.ml.classification import NaiveBayes nb = NaiveBayes(smoothing=1) model = nb.fit(trainingData) predictions = model.transform(testData) predictions.filter(predictions['prediction'] == 0) \ .select("Descript","Category","probability","label","prediction") \ .orderBy("probability", ascending=False) \ .show(n = 10, truncate = 30) from pyspark.ml.evaluation import MulticlassClassificationEvaluator evaluator = MulticlassClassificationEvaluator(predictionCol="prediction") evaluator.evaluate(predictions) |
随机森林 参数解释: ata:由LabeledPoint组成的rdd numClasses:分类任务时,有该参数,表示类别数量 impurity:节点的不纯度测量,对于分类可以使用gini系数或者信息熵,对回归只能是varainace maxDepth:数的最大深度,默认为5。 maxBins:在构建各节点时,将数据分到多少个箱子中 cateoricalFeaturesInfo:指定哪些特征是用于分类的,以及有多少个分类。 numTrees,即决策树的个数。 * featureSubsetStrategy:在每个节点上做决定时所考虑的特征的数量,可以是auto、all、sqrt、log2、onethird等,数目越大,计算的代价越大。 * seed:采用的随机数种子 |
from pyspark.ml.classification import RandomForestClassifier rf = RandomForestClassifier(labelCol="label", \ featuresCol="features", \ numTrees = 100, \ maxDepth = 4, \ maxBins = 32) # Train model with Training Data rfModel = rf.fit(trainingData) predictions = rfModel.transform(testData) predictions.filter(predictions['prediction'] == 0) \ .select("Descript","Category","probability","label","prediction") \ .orderBy("probability", ascending=False) \ .show(n = 10, truncate = 30) evaluator = MulticlassClassificationEvaluator(predictionCol="prediction") evaluator.evaluate(predictions) |
上面的结果可以看出:朴素贝叶斯是优秀的、鲁棒的通用模型。同样选择使用交叉验证的逻辑回归也是个明智的选择。但是选择交叉验证的逻辑回归时需要注意一点:由于使用了交叉验证,训练时间会过长,在实际的应用场景中要根据业务选择最合适的模型。
八.问题
-
Question:Hbase出现ERROR: Can't get master address from ZooKeeper; znode data == null解决办法
Reason: 出现此问题可能是zookeeper不稳定造成的,采用的是虚拟机,经常挂起的状态,使用hbase的list命令出现下面错误,这个可能是hbase的稳定性造成的。或者是运行hbase(zookeeper)的用户无法写入zookeeper文件,导致znode data为空。
Solution:方法一:重启hbase。Stop-hbase.sh start-hbase.sh
方法二:修改hbase-site.xml中的hbase.zookeeper.property.dataDir文件夹的权限,并注意rootdir中的IP设定很重要,需要设定对应的IP与hadoop下的core-site.xml中fs.defaultFS中的路径不相同,后重启hbase、zookeeper
-
Question:在使用sqoop进行一系列数据传输的小问题:
2.1:ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException:
2.2:ERROR mapreduce.ExportJobBase: Export job failed!
ERROR tool.ExportTool: Error during export:
Export job failed!
Solution:2.1 这个是由于mysql-connector-java的bug造成的,出错时我用的是mysql-connector-java-5.1.10-bin.jar,更新成mysql-connector-java-5.1.32-bin.jar就可以了。同时也要注意语句中ip的拼写
2.2 第一步:完整的检查mysql和hive表的结构(字段名称和数据类型)是否一致。
第二步:查看数据有没有导入?如果数据没有导入,请在检查第一步操作,可以将mysql和hive中的时间类型都改成string或varchar类型试一下。如果有导入,但是导入的数据不全或者不对。说明肯定是你的数据类型和实际的数据不一致。下面分两种情况。
第三步:在mysql到hive中,请务必检查你的数据中是否包含hive建表默认的换行符 \n (LINES TERMINATED BY '\n’)。
第四步:在mysql到hive中,请务必检查你的数据中是否包含hive建表常用的字段分隔符 \t(FIELDS TERMINATED BY '\t’)。如果有,则sqoop语句中 fields-terminated-by 参数不能用 \t
-
Question:Input path does not exist:hdfs://Master:9000/user/hive/wavehouse/crime.db/log
Reason:其实很简单,log是外部表,在对应hive数据库的存放地址内是访问不到的
Solution:需要建一个内部表复制一下外部表就可以访问到了
-
Question:在挂起回复以后,hbsae的子节点上的进程HRegionServer挂掉。
Reason:注意查看log日志报告的具体错误信息。ZooKeeper delete failed after 4 attempts,zookeeper对于Hmaster的选举产生了阻碍效果。Solution:
首先关闭Hbase、Zookeeper。查看Hbase自带zookeeper是否占用2181端口。
启动zookeeper
- 直接启动客户端脚本 zkCli.sh
- 查看Zookeeper节点信息 ls /
- 递归删除Hbase节点 rmr /hbase
- 退出客户端 quit
- 重启Zookeeper服务 zkServer.sh restart
当然也有可能是时间不一致导致的,注意同步各节点的时间
再启动Hbase即可。
九.小结
本次大作业的设计尽可能地运用到了本课程中所有的学习部分:Hadoop分布式处理框架、Hdfs分布式文件系统、Hbase分布式列存储数据库、Hive数据仓库、Zookeeper分布式协作服务、Spark基于内存的分布式计算框架、Sqoop数据同步工具。当作是我对本次课程的一次检测。当然还存在很多基础的框架应用等待我们学习如Kafka分布式消息队列、Flume日志收集工具Strom、Flink分布式流计算框架、Oozie工作流调度器等。大数据的学习永无止境!
本课设采用的数据集是旧金山的犯罪数据。虽然不是国内数据,时效也不太好,但是构成了一个完整的处理数据的流程。数据清洗,数据分析,数据建模,数据预测。当然在由于hive语句没有python熟练的缘故,Hql调用的比较少,只能简单查看一些。高级一些的数据属性之间的关联仍然是较少的。但好在在python可视化的时候,利用python做了一些数据的处理,也呈现出一些良好的效果,观察到一些有用的走势和波动。同样在数据建模的时候,运用的比较简单,对于数据降维,多属性数据的特征提取这类方法运用的不深。单纯的通过单一的模型来处理效果并不是很理想,需要我进一步利用网络对贝叶斯处理好的数据进行深层次的辨析。也许会得到更好的效果。当然在kaggle上也有很多大神在这个竞赛中提交了相当有趣的代码,例如xgboost和lightgbm,这值得我去学习,尝试着接下里来这些代码部署到spark中实现。
本次作业的完成,预示一段学习的结束,是对我这段时间学习的评价。同样也为我揭开了下一步学习的序幕。在实现各个过程中的细节和不足都成我继续前进的动力,对于更好更便捷的框架更吸引着我。
有时会发现学习是一件很快乐的事情 比一直跑步容易多了 不是嘛