Skip to content

Commit 82f7434

Browse files
committed
fix comments on lab words
1 parent fe4f73b commit 82f7434

File tree

2 files changed

+54
-21
lines changed

2 files changed

+54
-21
lines changed

compendium/modules/w07-setmap-lab.tex

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ \subsection{Bakgrund}
3434

3535
\subsection{Obligatoriska uppgifter}
3636

37+
Du ska bygga ditt program med en editor, t.ex. \texttt{atom}, och kompilera din kod i terminalen med \code{scalac} eller med hjälp av byggverktyget \code{sbt}. Medan du steg för steg utvecklar ditt program, ska du parallellt göra experiment i REPL för att undersöka hur du kan använda samlingsmetoder för att lösa uppgifterna.
38+
39+
Kod att utgå ifrån finns på github här: \url{https://github.com/lunduniversity/introprog/tree/master/workspace/w07_words}
40+
41+
Dessa ofärdiga kodfiler ligger i paketet \code{nlp}:
42+
\begin{itemize}
43+
\item \href{https://github.com/lunduniversity/introprog/blob/master/workspace/w07_words/src/main/scala/nlp/FreqMapBuilder.scala}{\texttt{FreqMapBuilder.scala}} innehåller ett skelett till en klass för att, ord för ord, bygga en nyckel-värde-tabell som registrerar antalet förekomster av olika ord. Att implementera denna ingick i övningen du gjorde tidigare i veckan.
44+
45+
\item \href{https://github.com/lunduniversity/introprog/blob/master/workspace/w07_words/src/main/scala/nlp/Text.scala}{\texttt{Text.scala}} innehåller ett skelett till en klass som kan göra textbehandling genom att analysera ord i en text.
46+
47+
\item \href{}{\texttt{}} \href{https://github.com/lunduniversity/introprog/blob/master/workspace/w07_words/src/main/scala/nlp/Main.scala}{\texttt{Main.scala}} innehåller ett ofärdigt huvudprogramsexempel som du kan använda i laborationens senare del.
48+
\end{itemize}
49+
50+
För att underlätta ditt arbetsflöde under det att du stegvis bygger upp din kod metod för metod, kan du med fördel använda byggverktyget \texttt{sbt} (se appendix \ref{appendix:build}) så här:
51+
52+
\begin{itemize}
53+
\item
54+
Med \code{sbt}-kommandot \code{console} startar du REPL innifrån \code{sbt} med dina klasser automatiskt tillgängliga på classpath och du kan anropa de metoder som du gjort färdigt hittills medan du gör experiment inför nästa steg. När du ändrat något i din editor och vill experimentera med nya versionen så trycker du Ctrl+D och startar om REPL med \code{console} (pil-upp) och din kod kompileras om automatiskt.
55+
\item
56+
Med \code{sbt}-kommandot \code{~run} (notera tilde-tecknet) sker kompilering och körning av \code{main}-metoden automatiskt i terminalen varje gång du gör Ctrl+S i din editor.
57+
58+
\end{itemize}
59+
3760

3861
\Task \emph{Skapa frekvenstabeller}. Du ska använda \code{FreqMapBuilder} från veckans övning för att skapa frekvenstabeller av typen \code{Map[String, Int]}, där nyckel-värde-paren i tabellen anger antalet förekomster av en viss sträng.
3962

@@ -64,11 +87,11 @@ \subsection{Obligatoriska uppgifter}
6487
res2: Map[String,Int] = Map(10292 -> 1, 19125 -> 1, 26985 -> 1, 29301 -> 1, 5451 -> 1, 4018 -> 1, 31211 -> 1, 17319 -> 1, 20778 -> 1, 25285 -> 1, 17079 -> 1, 9936 -> 1, 13172 -
6588
\end{REPL}
6689

67-
\noindent I kommande uppgifter ska du steg för steg skapa och testa case-klassen \code{Text} nedan. %figur \ref{data:fig-text}.
90+
\noindent I kommande uppgifter ska du steg för steg skapa och testa case-klassen \code{Text}. %figur \ref{data:fig-text}.
6891

6992

70-
\Task \emph{Dela upp en sträng i ord}. Medlemmen \code{words} ska innehålla en vektor med alla ord i \code{source}, utan andra tecken än bokstäver.
71-
Dela upp strängen \code{source} genom att i tur och ordnig göra följande:
93+
\Task \emph{Dela upp en sträng i ord}. Du ska implementera medlemmen \code{words}. Den ska innehålla en vektor med alla ord i \code{source}, utan andra tecken än bokstäver.
94+
Detta åstadkommer du genom att utgå ifrån strängen \code{source} och i tur och ordning göra följande:
7295
\begin{enumerate}%[nolistsep, noitemsep]
7396
\item byta ut alla tecken i \code{source} för vilka \code{isWhitespace} är sant mot \code{' '}
7497
\item byta sedan ut alla tecken för vilka \code{isLetter} är falskt mot \code{' '}
@@ -100,14 +123,14 @@ \subsection{Obligatoriska uppgifter}
100123

101124

102125

103-
\begin{figure}[t]
126+
\begin{figure}[H]
104127
\scalainputlisting[numbers=left,basicstyle=\ttfamily\fontsize{10.4}{12.5}\selectfont]{../workspace/w07_words/src/main/scala/nlp/Text.scala}
105128
%\caption{Den ofärdiga klassen \code{Text}.}
106129
%\label{data:fig-text}
107130
\end{figure}
108131

109132

110-
\Task Implementera \code{wordFreq} med hjälp av \code{FreqMapBuilder}. Testa \code{wordFreq} genom att ladda ner boken ''Skattkammarön'' skriven av Robert Louis Stevenson\footnote{Copyright för denna bok har gått ut, så du gör dig inte skyldig till piratkopiering (i juridisk mening).} och undersök frekvensen för olika vanliga ord. Vilket ord är vanligast? Näst vanligast?
133+
\Task Du ska nu skapa ordfrekvenstabellen \code{wordFreq} genom att registrera ordförekomster med hjälp av \code{FreqMapBuilder}. Tabellen \code{wordFreq} ska bestå av nyckelvärdepar \code{w -> f} där \code{f} är antalet gånger ordet \code{w} förekommer i \code{words}. Testa \code{wordFreq} genom att ladda ner boken ''Skattkammarön'' skriven av Robert Louis Stevenson\footnote{Copyright för denna bok har gått ut, så du gör dig inte skyldig till piratkopiering (i juridisk mening).} och undersök frekvensen för olika vanliga ord. Vilket ord är vanligast? Näst vanligast?
111134

112135
\begin{REPL}[basicstyle=\color{white}\ttfamily\fontsize{9}{11}\selectfont]
113136
scala> val piratbok = Text.fromURL("https://fileadmin.cs.lth.se/pgk/skattkammaron.txt")
@@ -132,7 +155,7 @@ \subsection{Obligatoriska uppgifter}
132155

133156

134157

135-
\Task Implementera metoden \code{ngrams}. \emph{Tips:} Undersök i REPL hur metoden \code{sliding} fungerar. Gör \code{toVector} på resultatet från \code{sliding}. Testa så att \code{ngrams} och \code{bigrams} fungerar.
158+
\Task Implementera metoden \code{ngrams} som ger en sekvens med alla ordföljder i $n$ steg. \emph{Tips:} På veckans övning ingick att undersöka hur metoden \code{sliding} fungerar, med vilken du kan skapa $n$-gram. Gör \code{toVector} på resultatet från \code{sliding}. Testa noga så att \code{ngrams} och \code{bigrams} fungerar korrekt innan du går vidare.
136159
\begin{REPL}
137160
scala> piratbok.ngrams(3).take(2)
138161
res1: scala.collection.immutable.Vector[Vector[String]] =
@@ -143,7 +166,11 @@ \subsection{Obligatoriska uppgifter}
143166
Vector((herr,trelawney), (trelawney,doktor))
144167
\end{REPL}
145168

146-
\Task Implementera \code{followFreq}, som ska innehålla en nyckel-värde-tabell där värdet i sin tur är en frekvenstabell över de ord som kommer efter nyckeln. Utgå från nedan pseudokod:
169+
\Task Implementera \code{followFreq}, som ska innehålla en nyckel-värde-tabell där värdet i sin tur är en frekvenstabell över de ord som kommer efter nyckeln.
170+
171+
Genom att analysera alla ordpar kan vi få fram vilket som är det vanligaste ordet som följer efter ett givet ord. Metoden \code{bigrams} ger oss alla ordpar \code{(w1, w2)} där \code{w2} följer efter \code{w1}. Vi kan spara statistiken över efterföljande ord i en nyckelvärdetabell med mappningarna \code{w -> f} där nyckeln \code{w} är ett ord och värdet \code{f} är en frekvenstabell av typen \code{Map[String, Int]}. I frekvenstabellen lagrar vi frekvensen för alla de ord som följer efter \code{w}. Du ska alltså bygga en nästlad tabell av typen \code{Map[String, Map[String, Int]]}. Rita en bild av den nästlade strukturen.\Pen
172+
173+
Implementera metoden followFreq genom att utgå från nedan pseudokod:
147174
\begin{Code}
148175
val result = scala.collection.mutable.Map.empty[String, FreqMapBuilder]
149176
for ((key, next) <- bigrams) {
@@ -154,6 +181,8 @@ \subsection{Obligatoriska uppgifter}
154181
}
155182
result.mapValues(_.toMap).toMap // returnerar oföränderligt objekt
156183
\end{Code}
184+
Skriv uttryck för att ta reda på följande:\Pen
185+
157186
\Subtask Vilka ord brukar följa efter \emph{han} respektive \emph{hon} i Stevensons ''Skattkammarön''?
158187

159188
\Subtask Vilka ord brukar följa efter \emph{han} respektive \emph{hon} i Stringbergs ''Inferno''?
@@ -198,7 +227,7 @@ \subsection{Kontrollfrågor}
198227

199228
\item Är mängden av alla nycklar i en nyckel-värde-tabell garanterat unika?
200229

201-
\item Är mängden av alla värden i en nyckel-värde-tabell garanterat unika?
230+
\item Är alla värden i en nyckel-värde-tabell garanterat unika?
202231

203232
\item LTH-teknologen Oddput Clementin vill summera längden på varje sträng i en mängd och skriver:
204233
\begin{REPL}
@@ -210,35 +239,39 @@ \subsection{Kontrollfrågor}
210239

211240
\subsection{Frivilliga uppgifter}
212241

213-
\Task Implementera nedan metod som ska ge ett slumpmässigt ord ur \code{wordSet}. Varje ord ska förekomma med lika stor sannolikhet.
242+
\Task Bygg vidare på klasse \code{Text} och implementera nedan metod som ska ge ett slumpmässigt ord ur \code{wordSet}. Varje ord ska förekomma med lika stor sannolikhet.
214243
\begin{Code}
215244
def randomWord: String = ???
216245
\end{Code}
217246

218-
\Task \label{task:words:randomSeq} Implementera nedan metod som ska ge en slumpmässig sekvens av $n$ ord där varje efterföljande ord väljs ur nyckelmängden för \code{followFreq} med lika stor sannolikhet.
247+
\Task \label{task:words:randomSeq} Med NLP kan man generera slumpmässiga meningar som statistiskt sett liknar ''riktiga'', människoskapade meningar.
248+
249+
Implementera metoden \code{randomSeq(firstWord, n)} nedan i klassen \code{Text}. Den ska ge en sekvens $w_{1}, w_{2}, ..., w_{n}$ där $w_{1}$ är \code{firstWord} och $w_{i+1}$ är något slumpmässigt ord som är draget bland de ord som följer efter $w_{i}$. Detta kan du åstadkomma genom att varje efterföljande ord $w_{i+1}$ väljs ur \code{keys.toVector} för den \code{followFreq}-tabell som hör till $w_{i}$. Orden ska dras med rektangelfördelad sannolikhet ur efterföljandemängden.
219250
\begin{Code}
220251
def randomSeq(firstWord: String, n: Int): Vector[String] = ???
221252
\end{Code}
222-
\emph{Tips:} Metoden \code{scala.util.Random.shuffle} tar en sekvens som argument och genererar en ny sekvens av samma typ, men med elementen ordnade i slumpmässig ordning, där varje möjlig ordning är lika sannolik.
253+
%\emph{Tips:} Ett sätt att garanterat välja slumpmässigt element med rektangelfördelning ur en sekvens är att använda metoden \code{scala.util.Random.shuffle} som tar en sekvens som argument och genererar en ny sekvens av samma typ, men med elementen ordnade i slumpmässig ordning på ett välblandat sätt, där varje möjlig ordning är lika sannolik.
254+
255+
\Task \label{task:words:mostCommonSeq} För att dina datorgenererade meningar verkligen ska likna mänskilgt språk kan vi skapa de mest sannolika meningarna av olika längder ur vår analys av ordfrekvenser.
223256

224-
\Task \label{task:words:mostCommonSeq} Lägg till metoden \code{mostCommonSeq} i klassen \code{Text} enligt nedan:
257+
Lägg till metoden \code{mostCommonSeq} i klassen \code{Text} enligt nedan:
225258
\begin{Code}
226259
def mostCommonSeq(firstWord: String, n: Int): Vector[String] = ???
227260
\end{Code}
228-
\Subtask Implementera metoden så att resultatet blir en sekvens med \code{n} ord. Sekvensen ska börja med \code{firstWord} och därefter följas av det ord som är det vanligaste efterföljande ordet efter \code{firstWord}, och därpå det vanligaste efterföljande ordet efter det, etc. \emph{Tips:} Använd en lokal variabel \code{val result} som är en ArrayBuffer till vilken du i en \code{while}-loop lägger de efterföljande orden.
261+
\Subtask Implementera metoden så att resultatet blir en sekvens med \code{n} ord. Sekvensen ska börja med \code{firstWord} och därefter följas av det ord som är det \emph{vanligaste} efterföljande ordet efter \code{firstWord}, och därpå det vanligaste efterföljande ordet efter det, etc. \emph{Tips:} Använd en lokal variabel \code{val result} som är en ArrayBuffer till vilken du i en \code{while}-loop lägger de efterföljande orden.
229262

230263
\Subtask Jämför de slumpmässiga sekvenserna med sekvenser genererade med \code{randomSeq} i uppgift \ref{task:words:randomSeq}. Vilka sekvenser liknar mest ''riktiga'' meningar?
231264

232265

233-
\Task Använd befintliga samlingsmetoder i stället för \code{FreqMapBuilder}.
266+
\Task Använd befintliga samlingsmetoder i stället för \code{FreqMapBuilder} för att registrera efterföljande ord.
234267

235268
\Subtask Undersök i REPL hur metoden \code{groupBy(x => x)} fungerar då den appliceras på en samling med strängar. Sök efter och studera dokumentationen för \code{groupBy}.
236269

237270
\Subtask Undersök i REPL hur metoden \code{mapValues} fungerar då den appliceras på en nyckel-värde-tabell där värdet är en samling. Sök efter och studera dokumentationen för \code{mapValues}.
238271

239272
\Subtask Inför värdet \code{lazy val wordFreq2}. Den ska ge samma resultat som \code{wordFreq} men men implementeras med hjälp av \code{groupBy} och \code{mapValues} i stället för \code{FreqMapBuilder}.
240273

241-
\Subtask Jämför prestanda mellan \code{wordFreq2} och \code{wordFreq}. Vilken är snabbast för stora texter? Är skillnaden stor?
274+
\Subtask\Uberkurs Jämför prestanda mellan \code{wordFreq2} och \code{wordFreq}. Vilken är snabbast för stora texter? Är skillnaden stor?
242275

243276
\Subtask Inför värdet \code{lazy val followsFreq2}. Den ska ge samma resultat som \code{followsFreq} men implementeras med hjälp av \code{groupBy} och \code{mapValues} i stället för \code{FreqMapBuilder}.
244277
Denna uppgift är ganska knepig. Experimentera dig fram i REPL, och bygg upp en lösning steg för steg. \emph{Tips:}
@@ -248,10 +281,10 @@ \subsection{Frivilliga uppgifter}
248281
.mapValues(_.map(???).groupBy(???).mapValues(???))
249282
\end{Code}
250283

251-
\Subtask Jämför prestanda mellan \code{followsFreq2} och \code{followsFreq}. Vilken är snabbast för stora texter? Är skillnaden stor?
284+
\Subtask\Uberkurs Jämför prestanda mellan \code{followsFreq2} och \code{followsFreq}. Vilken är snabbast för stora texter? Är skillnaden stor?
252285

253286

254-
\Task \emph{Gör \code{FreqMapBuilder} generisk.} Senare i kursen ska vi se hur man kan skapa s.k. generiska datastrukturer med hjälp av typparametrar. Denna uppgift går händelserna i förväg och tjuvkikar på hur en generisk klass kan se ut.
287+
\Task\Uberkurs \emph{Gör \code{FreqMapBuilder} generisk.} Senare i kursen ska vi se hur man kan skapa s.k. generiska datastrukturer med hjälp av typparametrar. Denna uppgift går händelserna i förväg och tjuvkikar på hur en generisk klass kan se ut.
255288

256289
\Subtask Studera \code{FreqMapBuilder} och identifiera allt i den klassen som är specifikt för typen \code{String}.
257290

workspace/w07_words/src/main/scala/nlp/Text.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
package nlp
22

33
case class Text(source: String){
4-
lazy val words: Vector[String] = ???
4+
lazy val words: Vector[String] = ??? // dela upp source i ord
55

66
lazy val distinct: Vector[String] = words.distinct
77

88
lazy val wordSet: Set[String] = words.toSet
99

1010
lazy val wordsOfLength: Map[Int, Set[String]] = wordSet.groupBy(_.length)
1111

12-
lazy val wordFreq: Map[String, Int] = ???
12+
lazy val wordFreq: Map[String, Int] = ??? // använd FreqMapBuilder
1313

14-
def ngrams(n: Int): Vector[Vector[String]] = ???
14+
def ngrams(n: Int): Vector[Vector[String]] = ??? // använd sliding
1515

1616
lazy val bigrams: Vector[(String, String)] =
1717
ngrams(2).map(xs => (xs(0), xs(1)))
1818

19-
lazy val followFreq: Map[String, Map[String, Int]] = ???
19+
lazy val followFreq: Map[String, Map[String, Int]] = ??? //nästlad tabell
2020

2121
lazy val follows: Map[String, String] =
2222
followFreq.mapValues(_.maxBy(_._2)._1)

0 commit comments

Comments
 (0)