构建 spark 机器学习系统
spark 机器学习系统架构
spark 和 hadoop 集群的安装
请参照下面的链接
spark-shell
- 1.x Spark-Shell 自动创建一个 SparkContext 对象 sc
- 2.x Spark-Shell 引入了 SparkSession 对象(spark),运行 Spark-Shell 会自动创建一个 SparkSession 对象,在输入 spark、SparkContext、SQLContext 都已经封装在 SparkSession 对象当中,它为用户提供了统一的的切入点,同时提供了各种DataFrame 和 DataSet 的API。
加载数据
- 原始数据。每个字段以 “,” 分割,源数据本来是以 “|” 分割的,但是实际处理中发现字段不能是Int(scala StructField 代码段,字段类型为IntegerType) 类型,否则程序会报错,这个有待进一步测试
列出3行样例数据
useid | age | gender | occupation | zipcode |
---|---|---|---|---|
1 | 24 | M | technician | 85711 |
2 | 53 | F | other | 94043 |
3 | 23 | M | writer | 32067 |
- 启动 pyspark
// python code
from pyspark import SparkConf,SparkContext
from pyspark.sql import SparkSession
from pyspark.sql import Row
spark = SparkSession.builder.appName("python spark SQL basic example").getOrCreate()
sc = spark.sparkContext
userrdd = sc.textFile("hdfs://master:9000/u01/bigdata/user_test.txt").map(lambda line: line.split(","))
df = userrdd.map(lambda fields: Row(userid = fields[0],age = int(fields[1]),gender = fields[2],occupation = fields[3],zipcode = fields[4]))
schemauser = spark.createDataFrame(df)
schemauser.createOrReplaceTempView("user")
schemauser.describe("userid","age","gender","occupation","zipcode").show()
// spark-submit
/data/spark/bin/spark-submit --master yarn \
--deploy-mode cluster \
--num-executors 2 \
--executor-memory '1024m' \
--executor-cores 1 \
/data/project/spark/python/load.py
// 注意如果有错误,将错误解决了,还是报同样的错误,那基本上可以肯定是缓存在作怪,需要删除当前目录下 "metastore_db" 这个目录。python 代码还可以直接提交 spark-submit load.py 只是这种方式使用的 spark standalone 集群管理模式
// scala code
package spark.mllib
import org.apache.spark.sql.Row
import org.apache.spark.sql.types._
import scala.collection.mutable
import org.apache.spark.{SparkConf,SparkContext}
object loadData {
def main(args: Array[String]) {
val userSchema: StructType = StructType(mutable.ArraySeq(
StructField("userid",IntegerType,nullable = false),
StructField("age",IntegerType,nullable = false),
StructField("gender",StringType,nullable = false),
StructField("occupation",StringType,nullable = false),
StructField("zipcode",StringType,nullable = false)
))
val conf = new SparkConf().setAppName("load data")
val sc = new SparkContext(conf)
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
val userData = sc.textFile("hdfs://master:9000/u01/bigdata/user_test.txt").map {
lines =>
val line = lines.split(",")
Row(line(0).toInt,line(1)toInt,line(2),line(3),line(4))
}
val userTable = sqlContext.createDataFrame(userData,userSchema)
userTable.registerTempTable("user")
userTable.describe("userid","age","gender","occupation","zipcode").show
sqlContext.sql("SELECT max(userid) as useridMax FROM user").show()
}
}
// spark-submit
/data/spark/bin/spark-submit --master yarn \
--deploy-mode cluster \
--num-executors 2 \
--executor-memory '1024m' \
--executor-cores 1 \
--class spark.mllib.loadData ./target/scala-2.11/mergefile_2.11-2.2.1.jar
关于 getOrCreate() 这个函数的使用方法详情见下面的链接
探索数据
数据统计信息
userTable.describe(“userid”,”age”,”gender”,”occupation”,”zipcode”).show
这一行代码会输出一个表格
summary | userid | age | gender | occupation | zipcode |
---|---|---|---|---|---|
count | 943 | 943 | 943 943 | 943 | 943 |
mean | 472.0 | 34.05196182396607 | null | null | 50868.78810810811 |
stddev | 272.3649512449549 | 12.19273973305903 | null | null | 30891.373254138158 |
min | 1 | 7 | F | administrator | 00000 |
max | 99 | 73 | M | writer | Y1A6B |
数据质量分析
- count 统计数据的总量,有多少条记录
- 总数
- 非空记录
- 空值 = 总数 - 非空记录
- mean 计算平均值
- std 标准差
- max 最大值
- min 最小值
- 百分位数:百分位数则是对应于百分位的实际数值。例如:将一个组数按小到大的顺序排序,25%=3.2,表示这组数中有25%的数是小于或等于3.2,75%的数是大于或等于3.2的。至于计算方式每个算法的计算方式不一样,pandas的计算方式没有找到。
- 25%
- 50%
- 75%
# linux服务器导入python matplotlib.pyplot报错
import matplotlib as mpl
mpl.use('Agg')
# 再执行
import matplotlib.pyplot as plt
# 需要保存图片到指定的目录
plt.savefig("/home/yourname/test.jpg")
# 即使是能够保持图片,但是图片传到Windows平台打开是空白的,画图看来最好还是要在Windows平台上执行
# 完整的代码,在Windows 平台上运行
# coding:utf-8
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("C:\\Users\\ljb\\Desktop\\catering_sale.csv")
print(df.count())
print(df.describe())
plt.figure()
bp = df.boxplot(return_type="dict")
# fliers 为异常数据标签
x = bp[ 'fliers' ][0].get_xdata()
y = bp[ 'fliers'][0].get_ydata()
y.sort()
print("x: ",x)
print("y: ",y)
# 用 annotate 添加注释
for i in range(len(x)):
plt.annotate(y[i],xy=(x[i],y[i]),xytext=(x[i] + 0.1 - 0.8/(y[i] - y[i-1]),y[i]))
plt.show()
/*
sale_date 200
sale_amt 198 从这里可以看出有2个空白的值
dtype: int64
sale_amt
count 198.000000
mean 2765.545152
std 709.557639
min 22.000000
25% 2452.725000
50% 2655.850000
75% 3023.500000
max 9106.440000
x: [ 1. 1. 1. 1. 1. 1.]
y: [ 22. 865. 1060. 4065.2 6607.4 9106.44]
*/
从上图可以看出有 6 个可能的异常值都在图上表现出来,但是具体是否异常,需要和销售人员确认
数据特征分析
特征:用于模型训练的变量。可以看做数据的属性。
1. 如果这些数据是记录人,那特征就是年龄,性别,籍贯,收入等。
2. 如果这些数据记录的是某个商品,那特征就是商品类别,价格,产地,生成日期,销售数量等
- 特征分布分析与相关性分析
- 有助于发现相关数据的分布特征、分布类型、分布是否邓超等,可以使用可视化方法,这样便于直观发现特征的异常值
- 对比分析
- 统计量分析
特征数据分析,例子
# coding:utf-8
from pyspark.sql import SparkSession
from pyspark.sql import Row
import matplotlib.pyplot as plt
import sys
spark = SparkSession.builder \
.appName("Python Spark SQL basic example") \
.getOrCreate()
sc = spark.sparkContext
userrdd = sc.textFile("C:\\Users\\ljb\\Desktop\\user_test.txt").map(lambda line:line.split(","))
df = userrdd.map(lambda fields: Row(userid = fields[0],age = int(fields[