参考:https://www.cnblogs.com/huajiezh/p/5790928.html
https://www.jianshu.com/p/0df3d5641c1c
java虚拟机的内存构造五个区域**(方法区&堆线程共享,本地栈&计数器&栈线程私有**)
jvm区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。
jvm垃圾收集算法及对应的回收机制
算法分三种(复制,标记清除,标记整理):新生代一般复制-整理算法,老年代一般标记整理清除算法
jvm垃圾回收的堆内存区域细分及常见gc(minorGC,majorGC,FullGC)的位置场景
minorGC发生在新生代的eden,sur区域,执行 Minor GC 操作时,不会影响到老年代。从老年代到年轻代的引用被当成 GC roots,从年轻代到老年代的引用在标记阶段被直接忽略掉
多次minorGC会触发MajorGC发生在老年代
fullGC会发生在什么区域,什么原因发生都不清楚!
最好避免以 Minor、Major、Full GC 这种方式来思考问题。而应该监控应用延迟或者吞吐量,需要关注stop the world
发生stop the world的情况:
Serial,parNew,cms的初始标记|并发标记都会产生
介绍GC 和GC Root不正常引用
介绍JVM中7个区域,然后把每个区域可能造成内存的溢出的情况说明
jvm 如何分配直接内存, new 对象如何不分配在堆而是栈上,常量池解析
数组多大放在 JVM 老年代(不只是设置 PretenureSizeThreshold ,问通常多大,没做过一问便知)
同步关键字synchronized
阻塞的两种情况:相对应没有阻塞同步代码执行完|发生异常就会释放锁
lock
lock和synchronized区别
ReentrantLock,意思是“可重入锁”,唯一实现lock接口
可重入性:
从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入的,两者关于这个的区别不大。两者都是同一个线程没进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。
想尽办法避免线程进入内核的阻塞状态是我们去分析和理解锁设计的关键钥匙。
参考:https://www.cnblogs.com/gxyandwmm/p/9387833.html
https://www.cnblogs.com/baizhanshi/p/7211802.html
公平锁:自己霸占锁,占用锁的状态值volatile累计(即重入性:a执行代码还没有释放锁,又执行其他任务了,b只能等待,后来a又进来代码块;所得占用状态值就增1)
非公平锁:插队(a释放锁唤醒b,b开始竞争,c过来了抢到了锁)
ReadWriteLock接口读写锁
ReentrantReadWriteLock实现了ReadWriteLock接口
concurrent包
是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发应用程序,主要包含原子量、并发集合、同步器、可重入锁,并对线程池的构造提供了强力的支持。
此处只介绍线程池:有五种创建方式
所谓给线程池提交任务,就是:
1、你将任务(业务处理逻辑)写到一个**runnable或者callable的执行方法
2、将这个runnable对象提交给线程池即可
BlockingQueue
主要的方法是:put、take一对阻塞存取;add、poll一对非阻塞存取
BlockingQueue有四个具体的实现类,常用的两种实现类为:LinkedBlockingQueue和ArrayBlockingQueue区别:
前者可以指定大小也可不指定默认Integer.MAX_VALUE决定吞吐量大;后者必须指定大小
都是FIFO(先入先出)顺序排序
atomicinteger和volatile等线程安全操作的关键字的理解和使用
线程间通信,wait和notify
java创建线程之后,直接调用start()方法和run()的区别
参考:https://blog.csdn.net/huyang0304/article/details/82290626
常见流就是字节流&字符流=》缓冲流=》对象流
A: close( ) 关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
B: flush( ) 仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
read()方法返回值为什么是int,而不是byte?
因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111,那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型。
如何实现对象克隆
1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;
2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
clone创建新对象:Clone() 只支持全局变量类型为8种基本类型和String类型的复制,对比如Date,ArrayList等其他引用类型(复合类型)只是复制了地址引用,这样Clone出来的对象就失去了原有的意义了,即成为浅度复制
我们在实现的clone()方法中,用序列化反序列化的方式得到一个新的Object并把它作为返回值返回,做深度复制即深度克隆:需要同事实现clone和序列化
NIO
阻塞和非阻塞是进程访问数据的时候,数据是否准备就绪的一种处理方式。
当数据没有准备好的时候
都是基于应用程序和操作系统处理IO事件所采用的方式
同步的方式处理IO事件的时候,必须阻塞在某个方法上线等待我们的IO事件完成(阻塞在io事件或者通过应用程序去轮询io事件(selector)的方式)即阻塞和轮询都是同步!
AIO:异步非阻塞
递归读取文件夹下的文件,代码怎么实现?
String类为什么是final的。
HashMap的源码,实现原理,底层结构|与hashtable区别|ConcurrentHashMap 底层实现原理与线程安全问题
string、stringbuilder、stringbuffer区别
Hash冲突怎么办?哪些解决散列冲突的方法
反射最大的作用就在于我们可以不在编译时知道某个对象的类型,而在运行时得到
至于动态代理和静态代理的区别,即动态代理是动态的创建代理和动态的处理方法的,这也是反射的一个重要体现之处。静态代理只需要重新实现原对象类的接口作为代理类,若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理。
类加载机制:
Class.forName和classloader的区别
Java中的队列都有哪些,有什么区别。
session和cookie的区别和联系,session的生命周期,多个服务部署时session管
spring如何实现事物管理的
springIOC
spring AOP的原理
同步和异步,阻塞和非阻塞。
HTTP协议、 HTTPS协议,SSL协议及完整交互过程;
head各个特点和区别
说说浏览器访问www.taobao.com,经历了怎样的过程。
将Java性能优化分为4个层级:应用层、数据库层、框架层、JVM层。每层优化难度逐级增加,涉及的知识和解决的问题也会不同。比如应用层需要理解代码逻辑,通过Java线程栈定位有问题代码行等;数据库层面需要分析SQL、定位死锁等;框架层需要懂源代码,理解框架机制;JVM 层需要对GC的类型和工作机制有深入了解,对各种 JVM 参数作用了然于胸;
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
将工厂也抽象了,在使用时,工厂和产品都是面向接口编程,OO(面向对象)的不得了
一句话总结工厂模式:方便创建 同种产品类型的 复杂参数 对象
工厂模式重点就是适用于 构建同产品类型(同一个接口 基类)的不同对象时,这些对象new很复杂,需要很多的参数,而这些参数中大部分都是固定的,so,懒惰的程序员便用工厂模式封装之。
(如果构建某个对象很复杂,需要很多参数,但这些参数大部分都是“不固定”的,应该使用Builder模式)
终端是哪个文件夹下的哪个文件?黑洞文件是哪个文件夹下的哪个命令?
终端 /dev/tty
黑洞文件 /dev/null
用什么命令对一个文件的内容进行统计?(行号、单词数、字节数)
wc 命令 - c 统计字节数 - l 统计行数 - w 统计字数。
搜索文件find <指定目录> <指定条件> <指定动作>
把后台任务调到前台执行使用什么命令?把停下的后台任务在后台执行起来用什么命令?
把后台任务调到前台执行 fg
把停下的后台任务在后台执行起来
后台运行命令
一般都是使用 & 在命令结尾来让程序自动运行。(命令后可以不追加空格)
查看进程状态
ps -aux|grep “”
ps -ef|grep “”
stat 中的参数意义如下:
D 不可中断 Uninterruptible(usually IO)
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
X 死掉的进程
< 高优先级
n 低优先级
s 包含子进程
+位于后台的进程组
7. df -hl
df,du区别:前者显示分区磁盘空间大小,后者显示目录和文件使用的存储空间大小
8. disown -r ’可以将所有正在运行的进程移除
输出命令+sort+head组合使用:
其中第一句主要是为了获取标题(USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND)。
接下来的grep -v PID是将ps aux命令得到的标题去掉,即grep不包含(-v)PID这三个字母组合的行,再将其中结果使用sort排序。
sort -rn -k +3该命令中的-rn的r表示是结果倒序排列,n为以数值大小排序,而-k +3则是针对第3列的内容进行排序,再使用head命令获取默认前5行数据。(其中的|表示管道操作)
官网文档http://hadoop.apache.org/docs/stable/
原理
写操作
读操作
源码
1.原理
注意:发送启动appmaster命令是RM做的事,上图有错
操作
1/ HIVE是什么?
HIVE是一个可以将sql翻译为MR程序的工具
HIVE支持用户将HDFS上的文件映射为表结构,然后用户就可以输入SQL对这些表(HDFS上的文件)进行查询分析
HIVE将用户定义的库、表结构等信息存储hive的元数据库(可以是本地derby,也可以是远程mysql)中
2/ HIVE的用途?
解放大数据分析程序员,不用自己写大量的mr程序来分析数据,只需要写sql脚本即可
HIVE可用于构建大数据体系下的数据仓库
3/ HIVE的使用方式?
方式1:可以交互式查询:
** bin/hive -----> hive>select * from t_test;
** 将hive启动为一个服务: bin/hiveserver ,然后可以在任意一台机器上使用beeline客户端连接hive服务,进行交互式查询
方式2:可以将hive作为命令一次性运行:
** bin/hive -e “sql1;sql2;sql3;sql4”
** 事先将sql语句写入一个文件比如 q.hql ,然后用hive命令执行: bin/hive -f q.hql
方式3:可以将方式2写入一个xxx.sh脚本中
4/ HIVE的DDL语法
建库: create database db1; —> hive就会在/user/hive/warehouse/下建一个文件夹: db1.db
建内部表:
use db1;
create table t_test1(id int,name string,age int,create_time bigint)
row format delimited
fields terminated by '\001';
建表后,hive会在仓库目录中建一个表目录: /user/hive/warehouse/db1.db/t_test1
建外部表:
create external table t_test1(id int,name string,age int,create_time bigint)
row format delimited
fields terminated by '\001'
location '/external/t_test';
导入数据:
本质上就是把数据文件放入表目录;
可以用hive命令来做:
hive>
load data [local] inpath '/data/path' [overwrite] into table t_test;
**建分区表:
分区的意义在于可以将数据分子目录存储,以便于查询时让数据读取范围更精准;
create table t_test1(id int,name string,age int,create_time bigint)
partitioned by (day string,country string)
row format delimited
fields terminated by '\001';
插入数据到指定分区:
hive> load data [local] inpath ‘/data/path1’ [overwrite] into table t_test partition(day=‘2017-06-04’,country=‘China’);
hive> load data [local] inpath ‘/data/path2’ [overwrite] into table t_test partition(day=‘2017-06-05’,country=‘China’);
hive> load data [local] inpath ‘/data/path3’ [overwrite] into table t_test partition(day=‘2017-06-04’,country=‘England’);
导入完成后,形成的目录结构如下:
/user/hive/warehouse/db1.db/t_test1/day=2017-06-04/country=China/…
/user/hive/warehouse/db1.db/t_test1/day=2017-06-04/country=England/…
/user/hive/warehouse/db1.db/t_test1/day=2017-06-05/country=China/…
表定义的修改:改表名、增加列,删除列,修改列定义…
5/ HIVE的DML
基本查询语法跟标准sql基本一致
SELECT FIELDS,FUNCTION(FIELDS)
FROM T1
JOIN T2
WHERE CONDITION
GROUP BY FILEDS
HAVING CONDTION
ORDER BY FIELDS DESC|ASC
各类JOIN语法跟SQL也基本一致,不过HIVE有一个自己的特别的JOIN: LEFT SEMI JOIN
hive在1.2.0之前不支持“不等值”join,但在1.2.0后支持不等值join,只是语法必须按如下形式写:
SELECT A.,B. from A,B WHERE A.ID>B.ID;
各类流程控制语句根SQL也基本一致:
case when l.userid is null
then concat('hive',rand())
when l.userid > 20
then concat('hive',rand())
else l.userid
6/ HIVE的内置函数
时间处理函数:
from_unixtime(21938792183,‘yyyy-MM-dd HH:mm:ss’) --> ‘2017-06-03 17:50:30’
类型转换函数:
from_unixtime(cast(‘21938792183’ as bigint),‘yyyy-MM-dd HH:mm:ss’)
字符串截取和拼接
substr(“abcd”,1,3) --> ‘abc’
concat(‘abc’,‘def’) --> ‘abcdef’
Json数据解析函数
get_json_object(’{“key1”:3333,“key2”:4444}’ , ‘$.key1’) --> 3333
json_tuple(’{“key1”:3333,“key2”:4444}’,‘key1’,‘key2’) as(key1,key2) --> 3333, 4444
url解析函数
parse_url_tuple(‘http://www.edu360.cn/bigdata/baoming?userid=8888’,‘HOST’,‘PATH’,‘QUERY’,'QUERY:userid’)
—> www.edu360.cn /bigdata/baoming userid=8888 8888
******* 函数:explode 和 lateral view
可以将一个数组变成列
加入有一个表,其中的字段为array类型
表数据:
1,zhangsan,数学:语文:英语:生物
2,lisi,数学:语文
3,wangwu,化学:计算机:java编程
建表:
create table t_xuanxiu(uid string,name string,kc array)
row format delimited
fields terminated by ‘,’
collection items terminated by ‘:’;
** explode效果示例:
select explode(kc) from t_xuanxiu where uid=1;
数学
语文
英语
生物
** lateral view 表生成函数
hive> select uid,name,tmp.* from t_xuanxiu
> lateral view explode(kc) tmp as course;
OK
1 zhangsan 数学
1 zhangsan 语文
1 zhangsan 英语
1 zhangsan 生物
2 lisi 数学
2 lisi 语文
3 wangwu 化学
3 wangwu 计算机
3 wangwu java编程
==== 利用explode和lateral view 实现hive版的wordcount
有以下数据:
a b c d e f g
a b c
e f g a
b c d b
对数据建表:
create table t_juzi(line string) row format delimited;
导入数据:
load data local inpath ‘/root/words.txt’ into table t_juzi;
** ***** ******** ***** ******** ***** ******** wordcount查询语句:***** ******** ***** ******** ***** ********
select a.word,count(1) cnt
from
(select tmp.* from t_juzi lateral view explode(split(line,' ')) tmp as word) a
group by a.word
order by cnt desc;
***************** ******** ***** ******** row_number() over() 函数***** ******** ***** ******** ***** ******** ***** ******** ***** *******
常用于求分组TOPN
有如下数据:
zhangsan,kc1,90
zhangsan,kc2,95
zhangsan,kc3,68
lisi,kc1,88
lisi,kc2,95
lisi,kc3,98
建表:
create table t_rowtest(name string,kcId string,score int)
row format delimited
fields terminated by ‘,’;
导入数据:
利用row_number() over() 函数看下效果:
select *,row_number() over(partition by name order by score desc) as rank from t_rowtest;
±----------------±----------------±-----------------±---------------------±-+
| t_rowtest.name | t_rowtest.kcid | t_rowtest.score | rank |
±----------------±----------------±-----------------±---------------------±-+
| lisi | kc3 | 98 | 1 |
| lisi | kc2 | 95 | 2 |
| lisi | kc1 | 88 | 3 |
| zhangsan | kc2 | 95 | 1 |
| zhangsan | kc1 | 90 | 2 |
| zhangsan | kc3 | 68 | 3 |
±----------------±----------------±-----------------±---------------------±-+
从而,求分组topn就变得很简单了:
select name,kcid,score
from
(select *,row_number() over(partition by name order by score desc) as rank from t_rowtest) tmp
where rank<3;
±----------±------±-------±-+
| name | kcid | score |
±----------±------±-------±-+
| lisi | kc3 | 98 |
| lisi | kc2 | 95 |
| zhangsan | kc2 | 95 |
| zhangsan | kc1 | 90 |
±----------±------±-------±-+
create table t_rate_topn_uid
as
select uid,movie,rate,ts
from
(select *,row_number() over(partition by uid order by rate desc) as rank from t_rate) tmp
where rank<11;
7/ 自定义函数 ***** ******** ***** ******** ***** ******** ***** ********
有如下数据:
1,zhangsan:18-1999063117:30:00-beijing
2,lisi:28-1989063117:30:00-shanghai
3,wangwu:20-1997063117:30:00-tieling
建表:
create table t_user_info(info string)
row format delimited;
导入数据:
load data local inpath ‘/root/udftest.data’ into table t_user_info;
需求:利用上表生成如下新表t_user:
uid,uname,age,birthday,address
思路:可以自定义一个函数parse_user_info(),能传入一行上述数据,返回切分好的字段
然后可以通过如下sql完成需求:
create t_user
as
select
parse_user_info(info,0) as uid,
parse_user_info(info,1) as uname,
parse_user_info(info,2) as age,
parse_user_info(info,3) as birthday_date,
parse_user_info(info,4) as birthday_time,
parse_user_info(info,5) as address
from t_user_info;
实现关键: 自定义parse_user_info() 函数
实现步骤:
1、写一个java类实现函数所需要的功能
public class UserInfoParser extends UDF{
// 1,zhangsan:18-1999063117:30:00-beijing
public String evaluate(String line,int index) {
String newLine = line.replaceAll(",", "\001").replaceAll(":", "\001").replaceAll("-", "\001");
StringBuilder sb = new StringBuilder();
String[] split = newLine.split("\001");
StringBuilder append = sb.append(split[0])
.append("\t")
.append(split[1])
.append("\t")
.append(split[2])
.append("\t")
.append(split[3].substring(0, 8))
.append("\t")
.append(split[3].substring(8, 10)).append(split[4]).append(split[5])
.append("\t")
.append(split[6]);
String res = append.toString();
return res.split("\t")[index];
}
}
2、将java类打成jar包: d:/up.jar
3、上传jar包到hive所在的机器上 /root/up.jar
4、在hive的提示符中添加jar包
hive> add jar /root/up.jar;
5、创建一个hive的自定义函数名 跟 写好的jar包中的java类对应
hive>
create temporary function parse_user_info as 'com.doit.hive.udf.UserInfoParser';
原理
原理
就是一个封装好mapreduce的工具(即写好特定功能的mr程序):实现关系型数据库与hadoop体系(hdfs,hive,hbase)
之间的数据转变和迁移!
sqoop不需要reduce就没有reduce.
导入关系表-mysql到HIVE
普通导入(相对单纯导入到hdfs上就是增加–hive-import关键字)
bin/sqoop import --connect jdbc:mysql://hdp-node-01:3306/test --username root --password root --table emp --hive-import --m 1
按需导入
bin/sqoop import \
--connect jdbc:mysql://hdp-node-01:3306/test \
--username root \
--password root \
--target-dir /wherequery2 \
--query 'select id,name,deg from emp WHERE id>1207 and $CONDITIONS' \
--split-by id \
--fields-terminated-by '\t' \
--m 2
从HIVE中导出数据到关系表(mysql)中
1、首先需要手动创建mysql中的目标表
$ mysql
mysql> USE db;
mysql> CREATE TABLE employee (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
deg VARCHAR(20),
salary INT,
dept VARCHAR(10));
2、然后执行导出命令
bin/sqoop export \+
--connect jdbc:mysql://hdp-node-01:3306/test \
--username root \
--password root \
--table employee \
--export-dir /user/hadoop/emp/
验证导出成功
mysql>select * from employee;
验证导出成功
mysql>select * from employee;
String,hset,sortedset
1.原理
http://homepage.cs.latrobe.edu.au/zhe/ZhenHeSparkRDDAPIExamples.html
mapPartitionsWithIndex
val func = (index: Int, iter: Iterator[(String)]) => {
iter.toList.map(x => "[partID:" + index + ", val: " + x + "]").iterator
}
mapPartitionsWithIndex
val func = (index: Int, iter: Iterator[(Int)]) => {
iter.toList.map(x => "[partID:" + index + ", val: " + x + "]").iterator
}
val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9), 2)
rdd1.mapPartitionsWithIndex(func).collect
------------------------------------------------------------------------------------
aggregate
def func1(index: Int, iter: Iterator[(Int)]) : Iterator[String] = {
iter.toList.map(x => "[partID:" + index + ", val: " + x + "]").iterator
}
val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9), 2)
rdd1.mapPartitionsWithIndex(func1).collect
rdd1.aggregate(0)(math.max(_, _), _ + _)
rdd1.aggregate(5)(math.max(_, _), _ + _)
val rdd2 = sc.parallelize(List("a","b","c","d","e","f"),2)
def func2(index: Int, iter: Iterator[(String)]) : Iterator[String] = {
iter.toList.map(x => "[partID:" + index + ", val: " + x + "]").iterator
}
rdd2.aggregate("")(_ + _, _ + _)
rdd2.aggregate("=")(_ + _, _ + _)
val rdd3 = sc.parallelize(List("12","23","345","4567"),2)
rdd3.aggregate("")((x,y) => math.max(x.length, y.length).toString, (x,y) => x + y)
val rdd4 = sc.parallelize(List("12","23","345",""),2)
rdd4.aggregate("")((x,y) => math.min(x.length, y.length).toString, (x,y) => x + y)
val rdd5 = sc.parallelize(List("12","23","","345"),2)
rdd5.aggregate("")((x,y) => math.min(x.length, y.length).toString, (x,y) => x + y)
------------------------------------------------------------------------------------
aggregateByKey
val pairRDD = sc.parallelize(List( ("cat",2), ("cat", 5), ("mouse", 4),("cat", 12), ("dog", 12), ("mouse", 2)), 2)
def func2(index: Int, iter: Iterator[(String, Int)]) : Iterator[String] = {
iter.toList.map(x => "[partID:" + index + ", val: " + x + "]").iterator
}
pairRDD.mapPartitionsWithIndex(func2).collect
pairRDD.aggregateByKey(0)(math.max(_, _), _ + _).collect
pairRDD.aggregateByKey(100)(math.max(_, _), _ + _).collect
------------------------------------------------------------------------------------
checkpoint
sc.setCheckpointDir("hdfs://node-1.edu360.cn:9000/ck")
val rdd = sc.textFile("hdfs://node-1.edu360.cn:9000/wc").flatMap(_.split(" ")).map((_, 1)).reduceByKey(_+_)
rdd.checkpoint
rdd.isCheckpointed
rdd.count
rdd.isCheckpointed
rdd.getCheckpointFile
------------------------------------------------------------------------------------
coalesce, repartition
val rdd1 = sc.parallelize(1 to 10, 10)
val rdd2 = rdd1.coalesce(2, false)
rdd2.partitions.length
------------------------------------------------------------------------------------
collectAsMap
val rdd = sc.parallelize(List(("a", 1), ("b", 2)))
rdd.collectAsMap
------------------------------------------------------------------------------------
combineByKey
val rdd1 = sc.textFile("hdfs://node-1.edu360.cn:9000/wc").flatMap(_.split(" ")).map((_, 1))
val rdd2 = rdd1.combineByKey(x => x, (a: Int, b: Int) => a + b, (m: Int, n: Int) => m + n)
rdd2.collect
val rdd3 = rdd1.combineByKey(x => x + 10, (a: Int, b: Int) => a + b, (m: Int, n: Int) => m + n)
rdd3.collect
val rdd4 = sc.parallelize(List("dog","cat","gnu","salmon","rabbit","turkey","wolf","bear","bee"), 3)
val rdd5 = sc.parallelize(List(1,1,2,2,2,1,2,2,2), 3)
val rdd6 = rdd5.zip(rdd4)
val rdd7 = rdd6.combineByKey(List(_), (x: List[String], y: String) => x :+ y, (m: List[String], n: List[String]) => m ++ n)
-----------------------------------------------------------------------------------
countByKey
val rdd1 = sc.parallelize(List(("a", 1), ("b", 2), ("b", 2), ("c", 2), ("c", 1)))
rdd1.countByKey
rdd1.countByValue
------------------------------------------------------------------------------------
filterByRange
val rdd1 = sc.parallelize(List(("e", 5), ("c", 3), ("d", 4), ("c", 2), ("a", 1)))
val rdd2 = rdd1.filterByRange("b", "d")
rdd2.colllect
------------------------------------------------------------------------------------
flatMapValues
val a = sc.parallelize(List(("a", "1 2"), ("b", "3 4")))
a.flatMapValues(_.split(" "))
-----------------------------------------------------------------------------------
foldByKey
val rdd1 = sc.parallelize(List("dog", "wolf", "cat", "bear"), 2)
val rdd2 = rdd1.map(x => (x.length, x))
val rdd3 = rdd2.foldByKey("")(_+_)
val rdd = sc.textFile("hdfs://node-1.edu360.cn:9000/wc").flatMap(_.split(" ")).map((_, 1))
rdd.foldByKey(0)(_+_)
------------------------------------------------------------------------------------
foreachPartition
val rdd1 = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
rdd1.foreachPartition(x => println(x.reduce(_ + _)))
-----------------------------------------------------------------------------------
keyBy
val rdd1 = sc.parallelize(List("dog", "salmon", "salmon", "rat", "elephant"), 3)
val rdd2 = rdd1.keyBy(_.length)
rdd2.collect
------------------------------------------------------------------------------------
keys values
val rdd1 = sc.parallelize(List("dog", "tiger", "lion", "cat", "panther", "eagle"), 2)
val rdd2 = rdd1.map(x => (x.length, x))
rdd2.keys.collect
rdd2.values.collect
------------------------------------------------------------------------------------
mapPartitions( it: Iterator => {it.map(x => x * 10)})
scala
函数定义
def xxname(int a):unit={
}
类定义(面向对象)
class xx{
}
object xx{
}
akka
机器学习
图计算
离线架构
空间复杂度:空间换时间,如:立flag
S(n)=O(f(n))
n是问题规模,f(n)是语句关于n所占空间的函数
O(1):高斯求累加,执行次数T(n)是常数;O(n)循环一次;O(n2):嵌套循环两次;O(n3):嵌套循环3次
**O(logn)**如下:
int i=1,n=100;
while(i
函数2^x=n得到x=log(2)n所以这个循环的时间复杂度按照以下攻略转换成O(logn)
O(1)
代码中先明确递归条件再调用递归,否则结束条件可能走不到。
插入:
for(int j=(v.length-2);j>=i;–j){//数组从0开始
v[j+1]=v[j];// 插入位置之后的元素右移!!!
}
v[i]=b;//插入b,表长赠一
删除:
for(int j=i+1;j
}
//单链表:
class SingleListNode {
int val;//数据域
SingleListNode next;//指针域
public SingleListNode(int val) {
this.val = val;
}
}
//双向链表:
public class ShuangXiangLianBiao<T> {
/**
* 内部类定义链表的数据结构
*/
private class ShuangXiangNode {
// 定义数据域
private T data;
// 前驱:上一个节点的引用
private ShuangXiangNode pre;
// 后继:下一个节点的引用
private ShuangXiangNode next;
}
// 保存链表的头节点
private ShuangXiangNode head;
// 保存链表的尾节点
private ShuangXiangNode tail;
// 链表的长度(链表节点数)
private int size;
// 基本操作类的构造方法
public ShuangXiangLianBiao() {
// 空链表tail,head都是null
head = null;
tail = null;
}
}
//循环链表:
public class CycaLinkList<T> {
// 创建一个内部节点类
private class Node {
// next引用
private Node next = null;
// 值
private T value = null;
// 构造方法
public Node() {
}
public Node(T value) {
this.value = value;
}
}
// 创建一个头节点
private Node head = null;
// 构造方法,对头节点初始化
public CycaLinkList() {
head = new Node(null);
head.next = head;//next指向自己
}
}
public class LinkQueue<T> {
// 链表的数据结构
private class Node {
public T data;
public Node next;//指针
//构造方法
public Node(){}
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
//需要有队列的头指针
private Node front;
// 队尾指针
private Node rear;
// 队列队长度
private int size=0;
//链表数据对象队构造方法
public LinkQueue(){
front=rear=null;
size=0;
}
}
/**
* 矩阵乘法函数:必须a的行数等于b的列数才能乘法运算
* @param a 矩阵因子a
* @param b 因子矩阵b
* @param c 目标矩阵
* @param x c的行数
* @param y c的列数
* @param z a矩阵的列数
*/
public static void MatrixMul(int[][] a,int[][] b,int[][] c,int x,int y, int z){
int i,j,k;
for ( j = 0; j < y; j++) {//清空目标矩阵
for (i = 0; i <x ; x++) {
c[j][i]=0;
}
}
for (j=0;j<y;j++){//进行矩阵乘法运算
for (i = 0; i < x; i++) {
for (k=0;k<z;k++){
c[j][i]+=a[j][k]*b[k][i];
}
}
}
}
/**
* majia
* 19-4-27
* 用于存储树中的节点
* 是节点和二叉树操作分离
*/
public class Node {
// 存储节点数据
private int value;
// 存储该节点的左孩子节点
private Node leftChild;
// 存储该节点的右孩子节点
private Node rightChild;
//构造方法
public Node(int value) {
this.value = value;
}
}
public class BinaryTree {
// 二叉树 根节点
private Node root = null;
//二叉树构造
public BinaryTree(int value) {
root = new Node(value);
root.setLeftChild(null);
root.setRightChild(null);
}
}
/**
* 二叉树的前序遍历
* @param node
*/
public void frontOrderNode(Node node){
if(node!=null){
// 访问根节点
System.out.println("节点:"+node.getValue());
// 遍历左子树
frontOrderNode(node.getLeftChild());
// 遍历右子树
frontOrderNode(node.getRightChild());
}
}
/**
* 二叉树的中序遍历
* @param node
*/
public void midOrderNode(Node node){//3,5,8左子树,30,35右树,10是根
if(node!=null){
// 遍历左子树
midOrderNode(node.getLeftChild());
// 遍历根节点
System.out.println(node.getValue());
// 遍历右子树
midOrderNode(node.getRightChild());
}
}
/**
* 二叉树的后续遍历
* @param node
*/
public void afterOrderNode(Node node){
if(node !=null){
// 遍历左子树
afterOrderNode(node.getLeftChild());
// 遍历右子树
afterOrderNode(node.getRightChild());
// 遍历根节点
System.out.println(node.getValue());
}
}
//伪代码深度优先
void DFS(int v)
visited[v]=true
for(v的每一个临接点w)
if(!visited[w])//如果没有访问过
DFS(w)
//广度优先
void BFS(int x)//伪代码
visited[x]=true
queue.push(x)
while(!Q.empty())
v=queue.pop()
for(v的每个临接点w)
if(!visisted[w])
visited[w]=true
queue.push(w)
public static int binarySearchDigui(int[] arr,int key,int low,int high){
if(low>high){//没找到
return -1;
}
int mid=(low+high)/2;
if(key==arr[mid]){//找到了
return mid;
}else if(key>arr[mid]){//递归右区间,key在右区间
return binarySearchDigui(arr,key,mid+1,high);
}else{//key在左区间
return binarySearchDigui(arr,key,low,mid-1);
}
}
/**
* 普通冒泡排序
* @param arr
* @param length
*/
private static void bubbleSort0(int[] arr, int length) {
for (int i = 0; i < length; i++) {
for (int j = 0; j < length - i - 1; j++) {
if(arr[j]>arr[j+1]){//前面的元素比后面的大就交换
swap(arr,j,j+1);
System.out.println("第"+(i+1)+"轮,元素"+arr[j]+"和元素"+arr[j+1]+"发生了交换");
}
}
}
}
/**
* majia
* 19-4-27
* 归并排序
* 数据的划分,递归进行
* 数据的归并,排序组合
* 升序示例
*/
public class GuiBingPaiXu {
public static void main(String[] args) {
int[] arr={1,9,2,8,7,4,3,};
System.out.println("排序前:");
for (int i : arr) {
System.out.print(i+" ");
}
System.out.println();
// 定义一个归并排序的算法
mergerSort(arr,0,arr.length-1);
System.out.println("排序后:");
for (int i : arr) {
System.out.print(i+" ");
}
}
/**
*
* @param arr 待排序数组
* @param start 开始位置
* @param end 结束位置
*/
private static void mergerSort(int[] arr, int start, int end) {
// 该方法要递归执行,要有出口条件:开始索引比结束索引大,或者数组中只有一个元素
if(start>=end){
return;
}
//平均的切分,找一个中点值
int mid=(start+end)/2;
// 递归待调用 左区间
mergerSort(arr,start,mid);
// 递归待调用 右区间
mergerSort(arr,mid+1,end);
//递归调用到最后,数组都是单元素,就不在递归,就要进行归并-排序-组合
merge(arr,start,mid,end);
}
/**
* 归并 的方法
* @param arr
* @param start 起始位置
* @param mid 中间位置
* @param end 结束位置
*/
private static void merge(int[] arr, int start, int mid, int end) {
// 需要合并的时候,就可以定义个临时数组,存储值
int[] tmp=new int[arr.length];
int i=start;//左区间探测
int j=mid+1;//这个指针,负责探测第二个区间(右区间)的值,
int size=0;//临时数组中的指针
for (;i<=mid&&j<=end;size++) {//i,j都是有区间限定的
if(arr[i]<arr[j]){//左右两个区间的元素(第一次进来两个区间是相同位置)进行比较,哪个值小,先放入tmp临时数组中
tmp[size]=arr[i++];//放入后i自增一,两句合一句
}else{//否则,右区间的值写入临时数组
tmp[size]=arr[j++];
}
}
//循环结束表明至少有一个区间的数据循环比较结束,
// 另外一个区间可能还右数据,没有结束,把这个空间剩余的所有值都存到临时数组中,归并完成
while(i<=mid){//左区间还没结束,有值
tmp[size++]=arr[i++];
}
while(j<=mid){//右区间还没结束,有值,把剩余所有值放入临时数组中
tmp[size++]=arr[j++];
}
// 临时数组是两个区间有序合并后的数据.
// 把tmp中的值再赋给arr
for (i = 0; i < size; i++) {
arr[start+i]=tmp[i];//start从0开始arr也是从0开始
}
}
}
def main(args: Array[String]): Unit = {
/* val conf = new SparkConf().setAppName(s"${this.getClass.getSimpleName}").setMaster("local[*]")
val sc = new SparkContext(conf)
val Array(inputPath) = Array(args(0))
val data = sc.textFile(inputPath)
// 数据预处理
val parseData: RDD[LabeledPoint] = data.map { line =>
val parts = line.split(",")
LabeledPoint(parts(0).toDouble, Vectors.dense(parts(1).split(" ").map(_.toDouble)))
}
// 将数据分为训练集(60%)和测试集(40%)
val splits = parseData.randomSplit(Array(0.6, 0.4), seed = 11L)
val training = splits(0)
val test = splits(1)
// 调用MLlib中的贝叶斯分类库,进行模型训练
val model = NaiveBayes.train(training, lambda = 1.0)
val predictionAndLabel = test.map(p=>(model.predict(p.features),p.label))
val accuracy=1.0* predictionAndLabel.filter(x=>x._1==x._2).count()/test.count()
// 保存并加载模型
model.save(sc,"myModelPath")
val sameModel = NaiveBayesModel.load(sc,"myModelPath")*/
//实时预测
newSessionLogs.filter(t=>model.predict(Utils.features(t))==2).print()
}
case class LabeledPoint(toDouble: Double, vector: linalg.Vector)
def main(args: Array[String]): Unit = {
// 本地运行模式
// new SparkConf().setSparkHome("/xxx/spark-bin-hadoop")
// 集群运行模式,读取spark集群的环境变量
// .setMaster("spark urls")
val conf = new SparkConf().setAppName("Recommendation")
val sc = new SparkContext(conf)
// 加载数据,路径式Azure Blob中离线数据的存储路径
val data = sc.textFile("/example/data.txt")
// 对rating Rdd的数据进行分解,只需要userid,moivedid,rating
val ratings = data.map(_.split("\t") match {
case Array(user, item, rate, time) => Rating(user.toInt, item.toInt, rate.toDouble)
})
//调用ALS算法进行模型训练
val model = new ALS()
// 配置算法参数
// setRank设置特征的数量
.setRank(params.rank)
// setIterations设这迭代次数
.setIterations(params.numIterrations)
// setLamda设置正则化因子
.setLambda(parallel.lambda)
// 设置用户数据块的个数和并行度
.setUserBlocks(params.numUserBlocks)
// 设置物品数据块个数和并行度
.setProductBlocks(params.numProductBlocks)
// 模型训练
// ratings每条记录为(userid,productid,rating)的rdd
.run(ratings)
// 电影预测
predictMovie(params,sc,model)
// 模型评估
evaluateMode(ratings,model)
}
/**
* 调用之前训练号的模型,对需要进行推荐对用户进行用户物品推荐,并最后评估检验模型效果
* @param params
* @param sc
* @param model
*/
def predictMovie(params:Params,sc:SparkContext,model:MatrixFactorizationModel): Unit ={
val recommenders = new util.ArrayList[util.Map[String,String]]()
// 读取需要进行电影推荐对用户数据
val userData= sc.textFile(params.userDataInput)
userData.map(_.split("\\|") match {
case Array(id,age,sex,job,x)=>(id)
}).collect().foreach(id=>{
// 为用户推荐电影
val rs = model.recommendProducts(id.toInt,numRecommender)
var value=""
var key=0
// 保存推荐数据到Azure Table中
rs.foreach(r=>{
key=r.user
value=value+r.product+":"+r.rating+","
})
// 成功则封装对象,等待保存到AzureTable中
if(!value.equals("")){
val put = new util.HashMap[String,String]()
put.put("rowKey",key.toString)
put.put("t:info",value)
recommenders.add(put)
}
})
// 保存到AzureTable的recommender表中
// recommenders是返回的java的ArrayList,可以自己用java或者scala写AzureTable的操作
// 工具类,用户调用AzureTable的API写入
// AzureUtil.saveListMap("recommender",recommenders)+
}
/**
* 评估模型的均方差
* @param ratings
* @param model
*/
def evaluateMode(ratings:RDD[Rating],model:MatrixFactorizationModel): Unit ={
//使用训练数据训练模型
val usersProducets = ratings.map(r => r match {
case Rating(user, product, tate) => (user, product)
})
// 预测数据
val predictions = model.predict(usersProducets).map(u => u match {
case Rating(user, product, rate) => ((user, product), rate)
})
// 将真是分数与预测分数进行合并
val ratesAndPreds = ratings.map(r => r match {
case Rating(user, product, rate) => ((user, product), rate)
}).join(predictions)
// 计算均方差
val MSE = ratesAndPreds.map(r => r match {
case ((user, product), (r1, r2)) =>
var err = (r1 - r2)
err * err
}).mean()
// 打印出均方差
println("Mean Squared Error="+MSE)
}
val nlpProps = {
val props = new Properties()
props.setProperty("annotators", "tokenize,ssplit,pos,lemma,parse,sentiment")
props
}
def detectSentiment(message:String):SENTIMENT_TYPE={
// 初始化
val pipeline=new StanfordCoreNLP(nlpProps)
// 处理输入对每一条twittter
val annotation = pipeline.process(message)
var sentiments:ListBuffer[Double]= ListBuffer()
var sizes:ListBuffer[Int]=ListBuffer()
var longest=0
var mainSentiment=0
// 针对解析出的每个句子进行情感分析
val maps: util.List[CoreMap] = annotation.get(classOf[CoreAnnotations.SentencesAnnotation])
for(sentence:CoreMap<- maps){
val tree = sentence.get(classOf[SentimentCoreAnnotations.SentimentAnnotatedTree])
val sentiment = RNNCoreAnnotations.getPredictedClass(tree)
val partText = sentence.toString
if(partText.length>longest){
mainSentiment = sentiment
longest=partText.length
}
sentiments+=sentiment.toDouble
sizes+=partText.length
}
// 求出整体的主流情感值,平均情感值,加权情感值
val averageSentiment = if(sentiments.size>0) sentiments.sum/sentiments.size
else -1
val weightedSentiments: ListBuffer[Double] = (sentiments,sizes).zipped.map((sentiment, size)=>sentiment*size)
var weightedSentiment = weightedSentiments.sum / (sizes.fold(0)(_ + _))
if(sentiments.size==0){
mainSentiment = -1
weightedSentiment = -1
}
println("debug:main:"+mainSentiment)
println("debug:avg:"+averageSentiment)
println("debug:weighted:"+weightedSentiment)
/**
* 0->very negative
* 1->negative
* 2->neutral
* 3->positive
* 4->very positive
*/
weightedSentiment match {
case s if s<=0.0 => NOT_UNDERSTOOD
case s if s<1.0 =>VERY_NEGATIVE
case s if s<2.0 => NEGATIVE
case s if s<3.0 => NEUTRAL
case s if s<4.0 => POSITIVE
case s if s<5.0 => VERY_POSITIVE
case s if s>5.0 => NOT_UNDERSTOOD
}
}
object XinWenJuLei {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("vsm-Kmeans").setMaster("local[*]")
val sc = new SparkContext(conf)
// 加载数据--特征提取--转化向量(通过HashingTF实现)
val documents = GetDocumentsFromMongoDB(sc)
val hashingTF = new HashingTF()
val tf = hashingTF.transform(documents)
// 当使用TF特征时只需要处理一遍数据;如果使用IDF特征需要处理两遍第一遍计算IDF向量,第二边通过IDF计算TF,IDF
//为了服用数据进行缓存
tf.cache()
/* val idf = new IDF().fit(tf)
val tfidf = idf.transform(tf)*/
// 计算IDF有一个参数能够忽略出现在过少文本中当单词使他们不再进行idf计算
val idf= new IDF(minDocFreq=2).fit(tf)
val tfidf = idf.transform(tf)
// 读入文件得到聚类结果
val parseData = parseData
val clusters = KMeans.train(parseData,numClusters,numIterations,parallRunNums)
// 聚类中心,每个聚类中心是和每个训练数据特征个数相同的向量
val centers = clusters.clusterCenters
// 聚类结果标签,将原有数据通过聚类出的中心点判断是哪些类别,并将文本标注出类别
val labels = clusters.predict(parseData)
// 保存结果
labels.saveAsTextFile("results.txt")
// }
}
class ShiShiReDian {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName(s"${this.getClass.getSimpleName}")
val sc = new SparkContext(conf)
val ssc = new StreamingContext(conf,Seconds(2))
// 获取实时新闻数据
val news = KafkaUtils.createKafkaStream(ssc, config)
val statuses = news.map(_.getText)
// 读取k-means模型
val model = new KMeansModel(ssc.sparkContext.objectFile[Vector](modelFile.toString).collect())
// 对新的新闻进行类别判断
val filteredNews=statuses.filter(this=>{
model.predict(Utils.featurize(t))==clusterNumber
})
filteredNews.print()
}
}
/**
* majia
* 19-5-1
* 确定最佳协同过滤模型参数
*/
object BestXieTong {
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local[*]", "BestALS")
// 1.读取电影信息到本地
val movies: Map[Int, String] = sc.textFile("movies.dat").map(line => {
val fields = line.split("::")
(fields(0).toInt, fields(1))
}).collect().toMap
// 2.读取评分数据RDD(Rating)
val ratings: RDD[(Long, Rating)] = sc.textFile("ratings.dat").map(line => {
val fields = line.split("::")
val rating = Rating(fields(0).toInt, fields(1).toInt, fields(2).toDouble)
val timestamp = fields(3).toLong % 10
(timestamp, rating)
})
// 3 输出数据集基本信息
val numRatings = ratings.count()
val numUsers = ratings.map(_._2.user).distinct().count
val numMovies = ratings.map(_._2.product).distinct().count()
println("Got" + numRatings + " ratings from " + numUsers + "users on" + numMovies + "movies")
// 4.利用taimstamp将数据集分为训练集(timestamp<6)和验证集(6 x._1 < 6).values.repartition(4).cache()
val validation = ratings.filter(x => x._1 >= 6 && x._1 < 8).values.repartition(4).cache()
val test = ratings.filter(x => x._1 >= 8).values.repartition(4).cache()
val numTraining = training.count()
val numValidation = validation.count()
val numTest = test.count()
println("Training:" + numTraining + " validation:" + numValidation + " test:" + numTest)
//5. 使用不同到参数训练协同过滤模型,并且选择出RMSE最小的模型
// 矩阵分解的秩从8-12选择,正则系统从1.0-10.0选择,迭代次数10-20次=>共计8个模型。可以根据实际情况调整
val ranks = List(8, 12)
val lambdas = List(1.0, 10.0)
val numIters = List(10, 20)
var bestModel: Option[MatrixFactorizationModel] = None
var bestValidationRmse = Double.MaxValue
var bestRank = 0
var bestLambda = -1.0
var bestNumIter = -1
for (rank <- ranks; lambda <- lambdas; numIter <- numIters) {
val model = ALS.train(training, rank, numIter, lambda)
val validationRmse = computeRmse(model, validation)
if (validationRmse < bestValidationRmse) {
bestModel = Some(model)
bestValidationRmse = validationRmse
bestRank = rank
bestLambda = lambda
bestNumIter = numIter
}
}
val testRmse = computeRmse(bestModel.get, test)
println("The best model was trained with rank=" + bestRank + " lambda=" + bestLambda + " numIter=" + bestNumIter + "" +
"and ites RMSEE on the best set is" + testRmse)
// 6.同时,还可以对比使用协同过滤算法和不使用系统过滤(例如:使用平均分作为预测结果)能得到多大的预测效果提升
val meanR = training.union(validation).map(_.rating).mean()
val baseRmse = math.sqrt(test.map(x => (meanR - x.rating) * (meanR - x.rating)).mean())
val imporvement = (baseRmse - testRmse) / baseRmse * 100
println("The best model improves the baseline by " + "%1.2f".format(imporvement) + "%.")
}
def computeRmse(model: MatrixFactorizationModel, data: RDD[Rating]) = {
// 定义函数计算均方误差RMSE
val predictions: RDD[Rating] = model.predict(data.map(x => (x.user, x.product)))
val predictiongsAndRatings = predictions.map(x => ((x.user, x.product), x.rating)).join(data.map(x => ((x.user, x.product), x.rating))).values
math.sqrt(predictiongsAndRatings.map(x => (x._1 - x._2) * (x._1 - x._2)).mean())
}
def tuiJian(sc: SparkContext, myRatings: RDD[Rating], movies: Map[Int, String], bestModel: Option[MatrixFactorizationModel]): Unit = {
// 7.利用最佳模型为用户推荐前10的电影
val myRatedMovieIds = myRatings.map(_.product).toSet
val cands = sc.parallelize(movies.keys.filter(!myRatedMovieIds.contains(_)).toSeq)
val recommendations = bestModel.get.predict(cands.map((0,_))).collect().sortBy(-_.rating).take(10)
var i=1
println("Movies recommended for you:")
recommendations.forech(r=>{
println("%2d".format(i)+":"+movies(r.product))
i+=1
})
}
}
基于商品
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local'*]", "itembase")
// 读取评分数据
val data = sc.textFile("sparkSampleData/mllib/als/test.data")
val parseData = data.map(_.split(",") match {
case Array(user, item, rate) => MatrixEntry(user.toLong - 1, item.toLong - 1, rate.toDouble)
})
val ratings = new CoordinateMatrix(parseData)
// 计算item相似度
val similarities = ratings.toRowMatrix().columnSimilarities(0.1)
// 计算项目1的平均评分
val ragingsOfItem1: Array[Double] = ratings.transpose().toRowMatrix().rows.collect()(0).toArray
val avgRatingOfItem1 = ragingsOfItem1.sum / ragingsOfItem1.size
// 计算用户1对其他项目对加权平均评分
val ratingsOfUser1 = ratings.toRowMatrix().rows.collect()(0).toArray.drop(1)
val weights = similarities.entries.filter(_.i == 0).sortBy(_.j).map(_.value).collect()
val weightedR: Double = (0 to 2).map(t => weights(t) * ratingsOfUser1(t)).sum / weights.sum
// 求和打印预测结果
println("Rating of user1 towards item1 is:" + (avgRatingOfItem1 + weightedR))
}
基于用户
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local[*]", "userbase")
val data = sc.textFile("sparkSampleData/mllib/als/test.data")
//将评分数据读到CoordinateMatrix中
val parsedData = data.map(_.split(",") match {
case Array(user, item, rate) => MatrixEntry(user.toLong - 1, item.toLong - 1, rate.toDouble)
})
val ratings: CoordinateMatrix = new CoordinateMatrix(parsedData)
// 将CoordinateMatrix转换为RowMatrix计算两两用户的余弦相似度,
// 因为RowMatrix只能比较列的相似度,而用户数据是用行表示的 ,因此CoordinateMatrix要先计算转置
val matrix = ratings.transpose().toRowMatrix()
val similarities = matrix.columnSimilarities(0.1)
// 假设需要预测用户1对项目1的评分,那么预测结果就是用户1的平均评分加上其他用户对项目1的按相似度的加权平均
// 计算用户1的评分
// val vector: linalg.Vector = ratings.toRowMatrix().rows.collect()(0)
val ratingsOfUser1 = ratings.toRowMatrix().rows.collect()(0).toArray
val avgRatingOfUser1 = ratingsOfUser1.sum / ratingsOfUser1.size
// 计算其他用户对项目1的加权平均评分
//matrix的一行,就是物品的所有用户评分,drop(1)表示删除自己的评分哈
val ratingsToItem1 = matrix.rows.collect()(0).toArray.drop(1)
// //权重_.i==0选择第一个用户,sortBy(_.j)表示根据用户的下标作为Key,value降序(value越大,表示相似度越高),所以,越前相似度越高
val weights = similarities.entries.filter(_.i == 0).sortBy(_.j).map(_.value).collect()
//(0 to 2)表示从0到2,默认步长1,这里表示,去top2相似的用户作为预测用户评分,真实情况,topn太少了哈
//sum(权重*用户评分)/sum(weights)
val weightedR = (0 to 2).map(t => weights(t) * ratingsToItem1(t)).sum / weights.sum
// 求和输出预测结果//把平均值+top2相似用户的加权平均值
println("Rating of user1 towards item1 is:" + (avgRatingOfUser1 + weightedR))
}
基于模型
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local[*]", "modelbase")
val data = sc.textFile("sparkSampleData/mllib/als/test.data")
val parseData = data.map(_.split(",") match {
case Array(user, item, rate) => MatrixEntry(user.toLong - 1, item.toLong - 1, rate.toDouble)
})
val ratings = new CoordinateMatrix(parseData)
// 将coord转换为rowMatrix,冰雕用computeSVD计算评分矩阵的秩为2的奇异值分解
val matrix = ratings.toRowMatrix()
val svd = matrix.computeSVD(2, true)
// 假设需要预测用户1对项目1的评分
val score = (0 to 1).map(t => svd.U.rows.collect()(0)(t) * svd.V.transpose.toArray(t))
// 打印预测结果
println("Rating of user1 towards item1 is:" + score.sum * svd.s(0))
}
val sc = new SparkContext("local[*]", "pagerank")
// 1.读取输入文件,将每一行的原始输入例如DADE,输出网页之间的链接关系,如(CA),(CD)(CE),并将结果换到到变量links中
val lines = sc.textFile("data/test_network.txt")
val links = lines.flatMap { line =>
val list = line.split("\\s+")
list.drop(1).map((list(0), _))
}.groupByKey().cache()
// 2.初始PageRank的值为1.0
var ranks = links.mapValues(v => 1.0)
// 3.迭代100次MapReduce,计算网页的PageRank值
for (i <- 1 to 100) {
/** map操作 */
/** 每一个网页对其他网页对贡献,是其当前对pagerank值初一连接数量,即rank/size
* 同时,对于没有输入链接的网页,其得到的pagerank贡献为0 */
val contribs = links.join(ranks).flatMap { case (urls, rank) =>
val size = urls.size
urls.map(url => (url, rank / size))
}.union(links.mapValues(v => 0.0))
/** Reduce操作 */
/** 网页的新PageRank值等于0.15+0.85倍的其得到的其他网页的pagerank贡献 */
ranks = contribs.reduceByKey(_ + _).mapValues(0.15 + 0.85 * _)
}
// 4输出结果
val output = ranks.sortByKey().collect()
output.foreach(println(_._1+" has rank: "+_._2))
val sc = new SparkContext("local[*]", "Rankingsvm")
// 1.使用MLUtils对象读取数据到RDD[LabeledPoint]
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/saple_libsvm_data.txt")
// 2.将新的训练集按3:2分为训练集和测试集
val splits = data.randomSplit(Array(0.6, 0.4))
val training = splits(0).cache()
val testing = splits(1)
// 3.设置迭代步骤100次,训练支持向量机模型
val model = SVMWithSGD.train(training, 100)
model.clearThreshold()
// 如果训练由正则项的支持向量机则修改为如下:
/* val svmAlg = new SVMWithSGD()
// L1正则,正则系数1.0,迭代100次
svmAlg.optimizer.setNumIterations(100).setRegParam(0.1).setUpdater(new L1Updater)
val model = svmAlg.run(training)*/
// 4. 预测测试集的分类结果
val scoreAndLabels = testing.map { point =>
val score = model.predict(point.features)
(score, point.label)
}
// 5.验证模型,包括模型的准确率,召回率,和F值
val metrics = new MulticlassMetrics(scoreAndLabels)
println("Precision=" + metrics.precision + ",Recall=" + metrics.recall + ",F-measure=" + metrics.fMeasure(1.0))
// 6.输出模型在权重最大的前10个特征和其权重
val weights = (1 to model.weights.size) zip model.weights.toArray
println("top 10 features:")
weights.sortBy(-_._2).take(10).foreach { case (k, w) => println("Feature " + k + "=" + w) }
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local[*]", "pujulei")
// 1.由于序奥计算社交网络的拉普拉斯矩阵L,因此要首先将网络读取到到CoordinateMatrix当中作为临接矩阵S
val data = sc.textFile("facebook/0.edges")
val adjMatrixEntry = data.map(_.split(" ") match {
case Array(id1, id2) => MatrixEntry(id1.toLong - 1, id2.toLong - 1, -1.0)
})
val adjMatrix = new CoordinateMatrix(adjMatrixEntry)
println("Num of nodes=" + adjMatrix.numCols() + ",Num of edges=" + data.count())
// 2.计算社交网络的拉普拉斯矩阵L=D-S
// 计算矩阵D的对角元素值
val rows: RDD[IndexedRow] = adjMatrix.toIndexedRowMatrix().rows
val diagMatrixEntry = rows.map(row => MatrixEntry(row.index, row.index, row.vector.toArray.sum))
// 计算拉普拉斯矩阵L=D-S
val laplaceMatrix = new CoordinateMatrix(sc.union(adjMatrixEntry, diagMatrixEntry))
// 3.计算拉普拉斯矩阵的特征列向量构成的矩阵(假设聚类个数示5)
val eigenMatrix = laplaceMatrix.toRowMatrix().computePrincipalComponents(5)
// 4.特征列向量矩阵的行向量就是网络中节点对应的5维向量表示
val nodes = eigenMatrix.transpose.toArray.grouped(5).toSeq
val nodeSeq = nodes.map(node => Vectors.dense(node))
val nodeVectors = sc.parallelize(nodeSeq)
// 5.求解节点在新向量表示下的K均值聚类结果
val clusters = new KMeans().setK(5).setMaxIterations(100).run(nodeVectors)
val result = clusters.predict(nodeVectors).zipWithIndex().groupByKey().sortByKey()
result.collect().foreach(c => {
println("NOdes in cluster " + (c._1 + 1) + ": " + c._2.foreach(n => print(" " + n)))
println()
})
}
效果看准确率,召回率,F值
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local[*]", "lianluyuce")
// 1.读取数据集
val data = sc.textFile("data/epinions/soc-sign-epinions.txt")
val parseData = data.map(_.split("\t") match {
case Array(id1, id2, sign) => (id1.toLong - 1, id2.toLong - 1, sign.toDouble)
})
// 2.创建节点对象VertexRDD和正边构成的EdgeRDD对象,用于构建Graph
val nodes: RDD[(VertexId, String)] = sc.parallelize(0L until (131828L)).map(id => (id, id.toString))
val edges: RDD[Edge[String]] = parseData.filter(_._3 == 1.0).map { case (id1, id2, sign) => Edge(id1, id2, id1 + "->" + id2) }
val network: Graph[String, String] = Graph(nodes, edges)
val network_ops: GraphOps[String, String] = network.ops
// 输出社交网络的节点数量和正边的数量
println("Number of nodes=" + network_ops.numVertices)
println("Number of edges=" + network_ops.numEdges)
// 3.为了简单,本案例中只统计节点的度作为分类特征:
val degrees = network_ops.degrees.map { case (id, degree) => (id.toLong, degree) }
val inDegrees: RDD[(VertexId, Int)] = network_ops.inDegrees.map { case (id, degree) => (id.toLong, degree) }
val outDegrees: RDD[(VertexId, Int)] = network_ops.outDegrees.map { case (id, degree) => (id.toLong, degree) }
// 4.将度特征整合到边到信息当中
val dataSet: RDD[(Double, Int, Int, Int, Int, Int, Int)] = parseData.map { case (id1, id2, sign) => (id1, (id2, sign)) }.join(degrees).join(inDegrees).join(outDegrees).map {
case (id1, ((((id2, sign), degree), inDegree), outDegree)) => (id2, (id1, sign, degree, inDegree, outDegree))
}.join(degrees).join(inDegrees).join(outDegrees).map {
case (id2, ((((id1, sign, degree1, inDregee1, outDegree1), degree2), inDegree2), outDegree2)) => (sign, degree1, inDregee1, outDegree1, degree2, inDegree2, outDegree2)
}
// 5.按照3:2划分训练样本和测试样本
val parsedDataSet: RDD[LabeledPoint] = dataSet.map { case (s, d1, d2, d3, d4, d5, d6) =>
if (s == 1.0) LabeledPoint(1.0, Vectors.dense(d1, d2, d3, d4, d5, d6))
else LabeledPoint(0.0, Vectors.dense(d1, d2, d3, d4, d5, d6))
}
val positiveDataSet = parsedDataSet.filter(_.label == 1.0)
val negativeDataSet = parsedDataSet.filter(_.label == 0)
val positiveSplits = positiveDataSet.randomSplit(Array(0.6, 0.4))
val negativeSplits = negativeDataSet.randomSplit(Array(0.6, 0.4))
val training = sc.union(positiveSplits(0), negativeSplits(0)).cache()
val testing = sc.union(positiveSplits(1), negativeSplits(1))
// 6.按照二分类问题训练Logistic回归模型
val model = new LogisticRegressionWithLBFGS().setNumClasses(2).run(training)
// 7.输出训练的模型在测试样本上的准确率和召回率:
val predictionAndLables = testing.map { case LabeledPoint(label, features) =>
val prediction = model.predict(features)
(prediction, label)
}
val metrics = new MulticlassMetrics(predictionAndLables)
println("Precision=" + metrics.precision(1.0))
println("Recall=" + metrics.recall(1.0))
// 8.输出每个特征的权值
val weights = (1 to model.numFeatures) zip model.weights.toArray
weights.foreach { case (k, w) => println("Feature " + k + "=" + w) }
}
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local[*]", "craoss validation")
// 1.首先利用CoordateMatrix读取数据集,并且整理成RDD[Long,Vector]
val data = sc.textFile("data/newsgroups/20news-bydate/matlab/train.data")
val matrixEntries = data.map { s =>
val splits = s.split(" ")
MatrixEntry(splits(0).toLong, splits(1).toLong, splits(2).toDouble)
}
val matrix = new CoordinateMatrix(matrixEntries)
val parsedData = matrix.toIndexedRowMatrix().rows.map(r => (r.index, r.vector))
println("Number of documents =%d,number of words=%d".format(matrix.numRows(), matrix.numCols()))
// 2.将数据均分为k份,randomSplit函数(5份)
val splits = parsedData.randomSplit(Array.fill(5)(1.0 / 5))
// 完整代码6.设定不同的主题个数N,计算不同主题个数时测试集的平均对数似然函数概率,平均对数似然概率最大时对应的主题个数N就是最佳的样本主题个数
// 测试15-25的主题个数
val rangeT = 15 to 25
val logLikelihood = Array.fill(11)(0.0)
rangeT.foreach { k =>
for (i <- 0 to 4) {
val training_index = (0 to 4).toArray.filter(_ != i)
//其中四个数据集作为训练集
val training_dataSet = sc.union(splits(training_index(0)), splits(training_index(1)), splits(training_index(2)), splits(training_index(3)))
// 训练主题个数为K的LDA模型
val ldaModel = new LDA().setK(k).run(training_dataSet)
// 返回归一化的主题分布,使用上一节定义的函数
val topicsMatrix = LDAModel.normalizedTopicsMatrix(ldaModel)
// 统计测试集的LogLikelihood
splits(i).collect().foreach { doc =>
val tokens = doc.toString().split(" ").filter(!_.isEmpty).map(_.toInt)
val posterior = LDAModel.interenceTopics(topicsMatrix, doc.toString(), 20, ldaModel)
tokens.foreach { id =>
val z = rangeT.map(t => posterior(t) * topicsMatrix(t)(id))
logLikelihood(k) += log(z.sum)
}
}
}
logLikelihood(k) /= 5
}
// 输出最大loglikelihood对应的主题个数
println("Best topic number=" + logLikelihood.indexOf(logLikelihood.max))
}
tag=>type: content:>url
tag标记即框,type:是类型后面必须空格,content是堆类型的内容填充
先定义tag,在用tag1->tag2->tag3的形式串成那个图!