Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Data Mining - технологии обработки больших данных. Учебное пособие
.pdf
Перед выполнением MapReduce-задачи смените текущую папку data
$ cd ../code
$ hadoop jar hadoop-streaming-2.7.2.jar -files mapper.py reducer.py -mapper
mapper.py -reducer reducer.py -input myInput -output myOutput
$ hs mapper.py reducer.py myInput jobOutput
$ hadoop fs -get jobOutput/part-00000 mylocalfile.txt
#!/usr/bin/python
import sys
for line in sys.stdin:
data = line.strip().split("\t")
if len(data) == 6:
date, time, store, item, cost, payment = data
if store.lower() in ['reno', 'toledo', 'chandler']:
print "{0}\t{1}".format(item, 1)
#!/usr/bin/python
import sys
salesMax = 0
oldKey = None
for line in sys.stdin:
data_mapped = line.strip().split("\t")
if len(data_mapped) != 2:
continue
thisKey, thisSale = data_mapped
if oldKey and oldKey != thisKey:
print oldKey, "\t", salesMax
oldKey = thisKey;
salesTotal = 0
oldKey = thisKey
if salesMax < float(thisSale):
salesMax = float(thisSale)
if oldKey != None:
print oldKey, "\t", salesMax
$ hs mapper.py reducer.py myinput myoutput
$ hadoop fs -cat myoutput/part-00000 | less
на папку code командой в терминале:
Запустите код на выполнение. Это можно несколькими командами в
терминале:
или
Если работа завершилась успешно, посмотрите результат MapReduce
задачи. Для этого скопируйте выходной файл jobOutput/part-00000 из HDFS
в файл mylocalfile.txt файловой системы виртуальной машины:
Задача 3. Найти максимальную стоимость покупки по каждому
магазину. Дополнительно указать полученные значения для магазинов Reno,
Toledo и Chandler.
Для решения задачи модифицируйте исходные файлы mapper.py и
reducer.py.
Реализация Mapper:
Реализация Reducer:
Выполните запуск MapReduce и выведите результат:
11

Задача 4. Найти общую сумму покупок и общее число покупок.
#!/usr/bin/python
import sys
for line in sys.stdin:
data = line.strip().split("\t")
if len(data) == 6:
date, time, store, item, cost, payment = data
print "{0}\t{1}".format(1, cost)
#!/usr/bin/python
import sys
salesTotal = 0
salesNumber = 0
for line in sys.stdin:
data_mapped = line.strip().split("\t")
if len(data_mapped) != 2:
# Something has gone wrong. Skip this line.
continue
thisKey, thisSale = data_mapped
salesNumber += float(thisKey)
salesTotal += float(thisSale)
print salesNumber, "\t", salesTotal
$ hs mapper.py reducer.py myinput myoutput
$ hadoop fs -cat myoutput/part-00000 | less
Для решения задачи модифицируйте исходные файлы mapper.py и
reducer.py.
Реализация Mapper:
Реализация Reducer:
Выполните запуск MapReduce и выведите результат:
Задача 5. Придумать и реализовать три новых интегрированных
запроса, содержащих, как минимум, три условия с логическими связками.
Результаты внести в отчет.
Ниже приведены ОБЩИЕ для всех практикумов требования к
содержанию отчетов. Каждый практикум требует обязательной личной
защиты.
Требования к оформлению и содержанию отчётов
Структура отчета:
титульный лист (с названием и номером практикума, ФИО студента),
цель, задачи,
ход выполнения,
программный код,
скриншоты, подтверждающие правильность выполнения MapReduce-
запросов,
полученные с помощью MapReduce-запросов данные,
выводы.
12

Практикум 1.2. Построение запросов MapReduce
Цель: проанализировать данные журнала транзакций веб-сайта.
к журналу транзакций веб-сайта
Задачи
1. Найти число посещений страницы "/assets/js/the-associates.js”.
2. Найти число посещений ip-адреса 10.99.99.186.
3. Найти самую посещаемую страницу и число её визитов.
4. Придумать и реализовать три новых интегрированных запроса,
содержащих, как минимум, три условия с логическими связками.
Ход выполнения
Данные для выполнения практикума находятся в файле access_log,
который размещен по адресу
/home/training/udacity_training/data/access_log.gz. Откройте домашнюю папку
“training’s Home” (рис. 1.7-1.8).
Рисунок 1.7 – Домашняя папка на рабочем столе
Перейдите в папку udacity_training –> data, откройте архивный файл
access_log.gz (рис. 1.9).
Рисунок 1.8 – Открытая домашняя папка
13

#!/usr/bin/python
import sys
for line in sys.stdin:
data = line.strip()
if data.find('/assets/js/the-associates.js') != -1:
print "{0}".format(1)
#!/usr/bin/python
import sys
count = 0
for line in sys.stdin:
data_mapped = line.strip()
count += int(data_mapped)
print count
Рисунок 1.9 – Содержимое архива
Содержимое архива переместите в папку data и поместите их в HDFS.
Файл access_log содержит информацию об обращениях к веб-
страницам. Файл представлен в формате CLG (The Common Log Format) и
имеет структуру %h %l %u %t \"%r\" %>s %b, где
• %h – IP-адрес клиента;
• %l – определить клиента или "-", если недоступно;
• %u – имя пользователя или клиента или "-", если недоступно;
• %t – время окончания обработки запроса сервером. Форма
[день/месяц/год:час:минуты:секунды:временная зона];
• %r – строка запроса, пришедшая от клиента (в двойных кавычках). Он
содержит метод, путь, строку запроса, а также протокол или запрос;
• %>s – это HTTP-код состояния, который сервер отправляет клиенту.
Вы увидите в основном коды состояния 200 (OK - запрос выполнен
успешно), 304 (не изменено) и 404 (не найдено);
• %b – размер объекта, возвращаемого клиенту, в байтах. Он будет «-» в
случае кода состояния 304.
Пример содержимого файла access_log
10.223.157.186 - - [15/Jul/2009:15:50:35 -0700] "GET
/assets/js/lowpro.js HTTP/1.1" 200 10469
Задача 1. Найти число посещений страницы “/assets/js/the-associates.js”.
Для решения задачи модифицируйте исходные файлы mapper.py и
reducer.py.
Реализация Mapper:
Реализация Reducer:
14

Задача 2. Найти число посещений ip-адреса 10.99.99.186.
#!/usr/bin/python
import sys
for line in sys.stdin:
data = line.strip().split(" ")
if '10.99.99.186' in data:
print "{0}".format(1)
#!/usr/bin/python
import sys
count = 0
for line in sys.stdin:
data_mapped = line.strip()
count += int(data_mapped)
print count
#!/usr/bin/python
import sys
import re
for line in sys.stdin:
data = line.strip().split(" ")
data[6] = re.sub('http://www.the-associates.co.uk','',data[6])
print("{0}\t{1}".format(data[6], 1))
#!/usr/bin/python
import sys
count = 0
page = None
pop_page_hits = 0
popular_page = None
for line in sys.stdin:
data = line.strip().split("\t")
if len(data) != 2:
continue
currPage, currCount = data
if page:
if page != currPage:
#print("{0}\t{1}".format(page, count))
if count > pop_page_hits:
pop_page_hits = count
popular_page = page
count = 1
page = currPage
else:
count += int(currCount)
else:
page = currPage
count += int(currCount)
print("{0}\t{1}".format(popular_page, pop_page_hits))
Для решения задачи модифицируйте исходные файлы mapper.py и
reducer.py.
Реализация Mapper:
Реализация Reducer:
Задача 3. Найти самую посещаемую страницу и число её визитов. При
этом исключите часть адреса, если она есть в адресах веб-страниц:
“http://www.the-associates.co.uk”
Для решения задачи модифицируйте исходные файлы mapper.py и
reducer.py.
Реализация Mapper:
Реализация Reducer:
15

Задача 4. Придумать и реализовать три новых интегрированных
запроса, содержащих, как минимум, три условия с логическими связками.
Результаты внести в отчет.
Таким образом, в ходе выполнения практикума получены практические
навыки реализации MapReduce задач на подготовленном файле, содержащем
информацию о логах посещений веб-сайта.
Для реализации MapReduce программ необходимо найти число
посещений на основе url адреса и ip ресурса, а также найти самую
посещаемую страницу, подсчитав число ее визитов.
16

Глава 2. Паттерны проектирования MapReduce
MapReduce является мощным средством для обработки больших
данных, однако имеет границы применимости с точки зрения эффективности.
Некоторые классы задач допускают общие подходы при обработке данных,
поэтому для сложных запросов целесообразно использовать паттерны
проектирования. Это повышает эффективность работы с MapReduce.
Рассмотрим основные паттерны проектирования.
Фильтрующие паттерны - не меняют фактические записи из набора
данных, а лишь выбирают те, которые удовлетворяют определенному
запросу. В результате получаем новый набор отфильтрованных данных.
Шаблон позволяет решать задачи выборки данных (семплирование),
генерации топ-листов и др.
Семплирование – это извлечение подмножества данных для
дальнейшей обработки, то есть выборка используется для извлечения
меньшего, но наиболее репрезентативного набора данных для дальнейшего
анализа.
Суммирующие паттерны - создают полный суммированный список
данных. Данные можно группировать, например, по полю, а затем вычислять
некоторые статистические величины.
Эти паттерны используют для числовых обобщений – поиск
минимальных, максимальных, средних(min / max / avg) и других численных
значений для набора данных, построения инвертированного индекса, котрый
используется при создании поисковой системы или полнотекстового поиска
для веб-сайта.
Структурные паттерны - решают проблемы реорганизации данных
для более простого их анализа с помощью MapReduce, то есть обеспечивают
возможность создания новых записей из данных, хранящихся в разных
структурах или источниках. Например, при переносе данных из РСУБД в
систему Hadoop данные должны быть переформатированы в более удобную
структуру. Для Hadoop не важен формат данных структуры. Можно
использовать иерархические данные, например, JSON или XML, чтобы
избежать выполнения совместных объединений нескольких наборов данных
во время их анализа.
Для применения данного паттерна необходимо выполнение
следующих условий: исходные данные должны быть связаны набором
внешних ключей (FK), структурированы и основаны на строках.
Combiner (полу-reducer) является необязательным классом, который
получает данные от mapper, а затем отправляет пары «ключ-значение» на
reducer. Основная функция - предобработка выхода mapper. Выход
комбайнера поступает на вход reducer, передавая агрегированный результат
для предобработанных mapper’ов. Важное отличие от reduce – на
комбинирующую функцию попадают не все значения, соответствующие
одному ключу. Однако Hadoop не гарантирует выполнение комбинирующей
17

функции, так как она не всегда применима, например, в случае поиска
#!/usr/bin/python
import sys
import csv
import re
def mapper():
reader = csv.reader(sys.stdin, delimiter='\t')
writer = csv.writer(sys.stdout, delimiter='\t', quotechar='"',
медианного значения по ключу.
MapReduce Combiner не имеет предопределенного интерфейса,
поэтому должен реализовать метод аналогичный функции свёртки; работает
на каждом выходе функции отображения, где должен формировать пару
«ключ-значение»; может подсчитать итоговый результат, т.к. заменяет
оригинальный выход mapper.
Практикум 2.1. Применение паттернов проектирования MapReduce
Цель: в данном практикуме рассматриваются паттерны
проектирования MapReduce запросов, включающие в себя: фильтрующие
паттерны; суммирующие паттерны; структурные паттерны.
Задача: выполнить MapReduce-запросы при помощи следующих
шаблонов.
1. Фильтрующие паттерны. Реализовать вывод строк, состоящих из
одного предложения или меньше.
2. Фильтрующие паттерны. Реализовать вывод топ-10 самых длинных
постов с форума.
3. Суммирующие паттерны. Составить инвертированный индекс по
текстам сообщений на форуме.
4. Суммирующие паттерны. Найти корреляцию между днем недели и
суммой денежных средств, которые потрачены на предметы.
5. Суммирующие паттерны. Подсчитать среднеарифметическое значение
всех покупок, совершенных в воскресенье, с использованием Combiner.
6. Структурные паттерны. Объединить два набора данных: сообщения с
форума и пользователей по полю id-автора.
7. Придумайте и реализуйте по три запроса на каждый вид паттерна.
Ход выполнения
Задача 1. Допишите код программы mapper, который должен
выполнять запрос к данным с форума Udacity и получать подмножество
данных, которое содержит одно предложение или меньше.
Переменная test_text содержит записи с форума. Допускается, что
могут быть символы “\n”. Все поля в двойных кавычках. Поэтому нужно
обработать данные без команды split(","). Для этого мы подключили
библиотеку csv в Python. Цель состоит в том, чтобы подсчитать количество
записей, которые либо не содержат ни одного из знаков: точку («.»),
восклицательный знак («!»), знак вопроса («?») или только один знак в конце
строки.
Реализация:
18

quoting=csv.QUOTE_ALL)
for line in reader:
tmp = re.split(r"[!?.]", line[4])
if len(tmp) < 2 or (len(tmp) == 2 and tmp[1] == ''):
writer.writerow(line)
test_text = """\"\"\t\"\"\t\"\"\t\"\"\t\"This is one sentence\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"Also one sentence!\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"Hey!\nTwo sentences!\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"One. Two! Three?\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"One Period. Two Sentences\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"Three\nlines, one sentence\n\"\t\"\"
"""
# This function allows you to test the mapper with the provided test string
def main():
import StringIO
sys.stdin = StringIO.StringIO(test_text)
mapper()
sys.stdin = sys.__stdin__
if __name__ == "__main__":
main()
Задача 2. Допишите код программы mapper, которая находит топ-10
#!/usr/bin/python
import sys
import csv
def mapper():
reader = csv.reader(sys.stdin, delimiter='\t')
writer = csv.writer(sys.stdout, delimiter='\t', quotechar='"',
quoting=csv.QUOTE_ALL)
top_dict = dict()
count=0
for line in reader:
top_dict[count] = line
count += 1
tmp = sorted(top_dict.items(), key=lambda x: len(x[1][4]))
nxt = len(tmp) - 10
for ln in range(len(tmp)):
if ln + nxt < len(tmp):
writer.writerow(tmp[ln + nxt][1])
test_text = """\"\"\t\"\"\t\"\"\t\"\"\t\"333\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"88888888\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"1\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"11111111111\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"1000000000\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"22\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"4444\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"666666\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"55555\"\t\"\"
\"\"\t\"\"\t\"\"\t\"\"\t\"999999999\"\t\"\"
самых длинных постов с форума.
MapReduce позволяет составить список топ N записей. В СУРБД,
например, сначала данные сортируются, а затем выделяются верхние N
записей. В MapReduce такой подход не будет работать, поскольку данные не
сортируются и обрабатываются на нескольких машинах. Таким образом,
функции отображения сначала должны найти свои собственные списки топ
N, не сортируя данные, а затем отправить локальные списки функциям
свёртки, которые создадут общий список топ N.
Реализация:
19

\"\"\t\"\"\t\"\"\t\"\"\t\"7777777\"\t\"\"
"""
# This function allows you to test the mapper with the provided test string
def main():
import StringIO
sys.stdin = StringIO.StringIO(test_text)
mapper()
sys.stdin = sys.__stdin__
main()
Задача 3. Напишите MapReduce-запрос, реализующий суммирующий
#!/usr/bin/env python
import sys
import re
import csv
reader = csv.reader(sys.stdin, delimiter='\t')
delimiters =
['.',',','$',';','!','?',':','"','(',')','[',']','<','>','#','=','-','/','
','\n','\t','\r','\f']
regex = '|'.join(map(re.escape, delimiters))
for line in reader:
node_id = line[0]
if node_id == "id":
continue
body = re.split(regex, line[4])
for token in body:
if len(token) > 0:
print "{0}\t{1}".format(node_id, token)
#!/usr/bin/env python
import sys
import re
import collections
inverted_index = collections.defaultdict(list)
for line in sys.stdin:
data = line.strip().split("\t")
if len(data) != 2:
continue
word = data[1].lower()
if word == 'fantastic' or word == 'fantastically':
inverted_index[word].append(data[0])
for word in inverted_index:
print "{0}\t{1}\t{2}".format(word, len(inverted_index[word]),
inverted_index[word])
паттерн для составления инвертированного индекса по текстам сообщений на
форуме. Для каждого слова надо вывести все id сообщений, в которых
данное слово встретилось. Найти: сколько раз слово “fantastic” встретилось
на форуме и выписать id всех записей, в которых было слово “fantastically”.
Реализация Mapper:
Реализация Reducer:
суммой денежных средств, которые потрачены на предметы. Задача - узнать
среднее и стандартное отклонения для продажи в день недели.
выполнять всю математику.
Задача 4. Требуется узнать, есть ли корреляция между днем недели и
Mapper выводит только день недели и сумму продажи. Reduce должен
20
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
