mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-10 22:21:11 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
f2d2937fef
@ -1,200 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (zhangxiangping)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (An attempt at implementing char-rnn with PyTorch)
|
||||
[#]: via: (https://jvns.ca/blog/2020/11/30/implement-char-rnn-in-pytorch/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
An attempt at implementing char-rnn with PyTorch
|
||||
======
|
||||
|
||||
Hello! I spent a bunch of time in the last couple of weeks implementing a version of [char-rnn][1] with PyTorch. I’d never trained a neural network before so this seemed like a fun way to start.
|
||||
|
||||
The idea here (from [The Unreasonable Effectiveness of Recurrent Neural Networks][1]) is that you can train a character-based recurrent neural network on some text and get surprisingly good results.
|
||||
|
||||
I didn’t quite get the results I was hoping for, but I wanted to share some example code & results in case it’s useful to anyone else getting started with PyTorch and RNNs.
|
||||
|
||||
Here’s the Jupyter notebook with the code: [char-rnn in PyTorch.ipynb][2]. If you click “Open in Colab” at the top, you can open it in Google’s Colab service where at least right now you can get a free GPU to do training on. The whole thing is maybe 75 lines of code, which I’ll attempt to somewhat explain in this blog post.
|
||||
|
||||
### step 1: prepare the data
|
||||
|
||||
First up: we download the data! I used [Hans Christian Anderson’s fairy tales][3] from Project Gutenberg.
|
||||
|
||||
```
|
||||
!wget -O fairy-tales.txt
|
||||
```
|
||||
|
||||
Here’s the code to prepare the data. I’m using the `Vocab` class from fastai, which can turn a bunch of letters into a “vocabulary” and then use that vocabulary to turn letters into numbers.
|
||||
|
||||
Then we’re left with a big array of numbers (`training_set`) that we can use to train a model.
|
||||
|
||||
```
|
||||
from fastai.text import *
|
||||
text = unidecode.unidecode(open('fairy-tales.txt').read())
|
||||
v = Vocab.create((x for x in text), max_vocab=400, min_freq=1)
|
||||
training_set = torch.Tensor(v.numericalize([x for x in text])).type(torch.LongTensor).cuda()
|
||||
num_letters = len(v.itos)
|
||||
```
|
||||
|
||||
### step 2: define a model
|
||||
|
||||
This is a wrapper around PyTorch’s LSTM class. It does 3 main things in addition to just wrapping the LSTM class:
|
||||
|
||||
1. one hot encode the input vectors, so that they’re the right dimension
|
||||
2. add another linear transformation after the LSTM, because the LSTM outputs a vector with size `hidden_size`, and we need a vector that has size `input_size` so that we can turn it into a character
|
||||
3. Save the LSTM hidden vector (which is actually 2 vectors) as an instance variable and run `.detach()` on it after every round. (I struggle to articulate what `.detach()` does, but my understanding is that it kind of “ends” the calculation of the derivative of the model)
|
||||
|
||||
|
||||
|
||||
```
|
||||
class MyLSTM(nn.Module):
|
||||
def __init__(self, input_size, hidden_size):
|
||||
super().__init__()
|
||||
self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True)
|
||||
self.h2o = nn.Linear(hidden_size, input_size)
|
||||
self.input_size=input_size
|
||||
self.hidden = None
|
||||
|
||||
def forward(self, input):
|
||||
input = torch.nn.functional.one_hot(input, num_classes=self.input_size).type(torch.FloatTensor).cuda().unsqueeze(0)
|
||||
if self.hidden is None:
|
||||
l_output, self.hidden = self.lstm(input)
|
||||
else:
|
||||
l_output, self.hidden = self.lstm(input, self.hidden)
|
||||
self.hidden = (self.hidden[0].detach(), self.hidden[1].detach())
|
||||
|
||||
return self.h2o(l_output)
|
||||
```
|
||||
|
||||
This code also does something kind of magical that isn’t obvious at all – if you pass it in a vector of inputs (like [1,2,3,4,5,6]), corresponding to 6 letters, my understanding is that `nn.LSTM` will internally update the hidden vector 6 times using [backpropagation through time][4].
|
||||
|
||||
### step 3: write some training code
|
||||
|
||||
This model won’t just train itself!
|
||||
|
||||
I started out trying to use a training helper class from the `fastai` library (which is a wrapper around PyTorch). I found that kind of confusing because I didn’t understand what it was doing, so I ended up writing my own training code.
|
||||
|
||||
Here’s some code to show basically what 1 round of training looks like (the `epoch()` method). Basically what this is doing is repeatedly:
|
||||
|
||||
1. Give the RNN a string like `and they ought not to teas` (as a vector of numbers, of course)
|
||||
2. Get the prediction for the next letter
|
||||
3. Compute the loss between what the RNN predicted, and the real next letter (`e`, because tease ends in `e`)
|
||||
4. Calculate the gradient (`loss.backward()`)
|
||||
5. Change the weights in the model in the direction of the gradient (`self.optimizer.step()`)
|
||||
|
||||
|
||||
|
||||
```
|
||||
class Trainer():
|
||||
def __init__(self):
|
||||
self.rnn = MyLSTM(input_size, hidden_size).cuda()
|
||||
self.optimizer = torch.optim.Adam(self.rnn.parameters(), amsgrad=True, lr=lr)
|
||||
def epoch(self):
|
||||
i = 0
|
||||
while i < len(training_set) - 40:
|
||||
seq_len = random.randint(10, 40)
|
||||
input, target = training_set[i:i+seq_len],training_set[i+1:i+1+seq_len]
|
||||
i += seq_len
|
||||
# forward pass
|
||||
output = self.rnn(input)
|
||||
loss = F.cross_entropy(output.squeeze()[-1:], target[-1:])
|
||||
# compute gradients and take optimizer step
|
||||
self.optimizer.zero_grad()
|
||||
loss.backward()
|
||||
self.optimizer.step()
|
||||
```
|
||||
|
||||
### let `nn.LSTM` do backpropagation through time, don’t do it myself
|
||||
|
||||
Originally I wrote my own code to pass in 1 letter at a time to the LSTM and then periodically compute the derivative, kind of like this:
|
||||
|
||||
```
|
||||
for i in range(20):
|
||||
input, target = next(iter)
|
||||
output, hidden = self.lstm(input, hidden)
|
||||
loss = F.cross_entropy(output, target)
|
||||
hidden = hidden.detach()
|
||||
self.optimizer.zero_grad()
|
||||
loss.backward()
|
||||
self.optimizer.step()
|
||||
```
|
||||
|
||||
This passes in 20 letters (one at a time), and then takes a training step at the end. This is called [backpropagation through time][4] and Karpathy mentions using this method in his blog post.
|
||||
|
||||
This kind of worked, but my loss would go down for a while and then kind of spike later in training. I still don’t understand why this happened, but when I switched to instead just passing in 20 characters at a time to the LSTM (as the `seq_len` dimension) and letting it do the backpropagation itself, things got a lot better.
|
||||
|
||||
### step 4: train the model!
|
||||
|
||||
I reran this training code over the same data maybe 300 times, until I got bored and it started outputting text that looked vaguely like English. This took about an hour or so.
|
||||
|
||||
In this case I didn’t really care too much about overfitting, but if you were doing this for a Real Reason it would be good to run it on a validation set.
|
||||
|
||||
### step 5: generate some output!
|
||||
|
||||
The last thing we need to do is to generate some output from the model! I wrote some helper methods to generate text from the model (`make_preds` and `next_pred`). It’s mostly just trying to get the dimensions of things right, but here’s the main important bit:
|
||||
|
||||
```
|
||||
output = rnn(input)
|
||||
prediction_vector = F.softmax(output/temperature)
|
||||
letter = v.textify(torch.multinomial(prediction_vector, 1).flatten(), sep='').replace('_', ' ')
|
||||
```
|
||||
|
||||
Basically what’s going on here is that
|
||||
|
||||
1. the RNN outputs a vector of numbers (`output`), one for each letter/punctuation in our alphabet.
|
||||
2. The `output` vector isn’t **yet** a vector of probabilities, so `F.softmax(output/temperature)` turns it into a bunch of probabilities (aka “numbers that add up to 1”). `temperature` kind of controls how much to weight higher probabilities – in the limit if you set temperature=0.0000001, it’ll always pick the letter with the highest probability.
|
||||
3. `torch.multinomial(prediction_vector)` takes the vector of probabilities and uses those probabilites to pick an index in the vector (like 12)
|
||||
4. `v.textify` turns “12” into a letter
|
||||
|
||||
|
||||
|
||||
If we want 300 characters worth of text, we just repeat this process 300 times.
|
||||
|
||||
### the results!
|
||||
|
||||
Here’s some generated output from the model where I set `temperature = 1` in the prediction function. It’s kind of like English, which is pretty impressive given that this model needed to “learn” English from scratch and is totally based on character sequences.
|
||||
|
||||
It doesn’t make any _sense_, but what did we expect really.
|
||||
|
||||
> “An who was you colotal said that have to have been a little crimantable and beamed home the beetle. “I shall be in the head of the green for the sound of the wood. The pastor. “I child hand through the emperor’s sorthes, where the mother was a great deal down the conscious, which are all the gleam of the wood they saw the last great of the emperor’s forments, the house of a large gone there was nothing of the wonded the sound of which she saw in the converse of the beetle. “I shall know happy to him. This stories herself and the sound of the young mons feathery in the green safe.”
|
||||
>
|
||||
> “That was the pastor. The some and hand on the water sound of the beauty be and home to have been consider and tree and the face. The some to the froghesses and stringing to the sea, and the yellow was too intention, he was not a warm to the pastor. The pastor which are the faten to go and the world from the bell, why really the laborer’s back of most handsome that she was a caperven and the confectioned and thoughts were seated to have great made
|
||||
|
||||
Here’s some more generated output at `temperature=0.1`, which weights its character choices closer to “just pick the highest probability character every time”. This makes the output a lot more repetitive:
|
||||
|
||||
> ole the sound of the beauty of the beetle. “She was a great emperor of the sea, and the sun was so warm to the confectioned the beetle. “I shall be so many for the beetle. “I shall be so many for the beetle. “I shall be so standen for the world, and the sun was so warm to the sea, and the sun was so warm to the sea, and the sound of the world from the bell, where the beetle was the sea, and the sound of the world from the bell, where the beetle was the sea, and the sound of the wood flowers and the sound of the wood, and the sound of the world from the bell, where the world from the wood, and the sound of the
|
||||
|
||||
It’s weirdly obsessed with beetles and confectioners, and the sun, and the sea. Seems fine!
|
||||
|
||||
### that’s all!
|
||||
|
||||
my results are nowhere near as good as Karpathy’s so far, maybe due to one of the following:
|
||||
|
||||
1. not enough training data
|
||||
2. I got bored with training after an hour and didn’t have the patience to babysit the Colab notebook for longer
|
||||
3. he used a 2-layer LSTM with more hidden parameters than me, I have 1 layer
|
||||
4. something else entirely
|
||||
|
||||
|
||||
|
||||
But I got some vaguely coherent results! Hooray!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2020/11/30/implement-char-rnn-in-pytorch/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zhangxiangping](https://github.com/zxp93)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://karpathy.github.io/2015/05/21/rnn-effectiveness/
|
||||
[2]: https://gist.github.com/jvns/b6dda36b2fdcc02b833ed5b0c7a09112
|
||||
[3]: https://www.gutenberg.org/cache/epub/27200/pg27200.txt
|
||||
[4]: https://en.wikipedia.org/wiki/Backpropagation_through_time
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -0,0 +1,121 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How I use Stream Deck on Linux with open source tools)
|
||||
[#]: via: (https://opensource.com/article/20/12/stream-deck)
|
||||
[#]: author: (Lorna Mitchell https://opensource.com/users/lornajane)
|
||||
|
||||
How I use Stream Deck on Linux with open source tools
|
||||
======
|
||||
Stream Deck is not just a keypad full of shiny buttons; it's a
|
||||
customizable workhorse that makes it easier to manage your video
|
||||
streams.
|
||||
![Working from home at a laptop][1]
|
||||
|
||||
Most of us have gotten a lot more familiar with working from home this year. In my role as a developer advocate, this has meant a lot less travel and a lot more video work, including [streaming on Twitch][2].
|
||||
|
||||
As I transitioned to working and streaming video from home in spring 2020, I decided to get a [Stream Deck][3], but I wasn't exactly sure what I'd use it for.
|
||||
|
||||
The Stream Deck is a keypad that makes it easier to manage your video streaming. You can customize its buttons to do things like switching scenes, adjusting audio, inserting media, interacting with viewers, and much more. I got the 32-button version because that's all that was in stock anywhere when I bought it.
|
||||
|
||||
![Lorna's video streaming setup][4]
|
||||
|
||||
(Lorna Mitchell, [CC BY-SA 4.0][5])
|
||||
|
||||
Six months in, it's become my best desk accessory. I want to introduce you to it and share my current setup.
|
||||
|
||||
### Stream Deck software for Linux
|
||||
|
||||
Stream Deck offers several software options for driving the device, but I'm on Ubuntu Linux, so the official Stream Deck tools aren't an option. I found a Python graphical user interface (GUI), but it really just mapped shell scripts onto buttons; since I don't use a mouse, I found the interface pretty awkward.
|
||||
|
||||
Instead, I glued together a lovely selection of open source libraries and created [a rather weird and knobbly Golang application][6] that perfectly suits my needs. That sounds like the hard way to drive some perfectly good hardware. Perhaps it is, but now that it's finished, it fits me perfectly, and I love it! I'm going to claim it's not purely a "works-on-my-machine" solution because it works on both of my Thinkpads running Ubuntu.
|
||||
|
||||
### Meet my Stream Deck
|
||||
|
||||
![Stream Deck][7]
|
||||
|
||||
(Lorna Mitchell, [CC BY-SA 4.0][5])
|
||||
|
||||
My setup is still changing weekly, but here's how it looks in November 2020. The top row is [Open Broadcaster Software][8] (OBS) integration; the second row is mainly bot/chat integration and window-focusing with a bonus screenshot button on the end; row three holds the lighting controls and a little bit of Twitch API integration; and the bottom row has sound effects and the all-important mute button. If you'd like a bit more detail, read on.
|
||||
|
||||
#### Start with streaming
|
||||
|
||||
It's a Stream Deck; the clue is in the name! So I began by adding some integration with OBS, the program I use to stream. OBS has a [plugin to support WebSockets][9], and there was already a [library for Golang][10], which really helped. Crucially, the library also handles events, so I have buttons that select scenes and a little indicator to show which scene is active—even if I change scenes via OBS rather than the Stream Deck.
|
||||
|
||||
Using the Stream Deck to change scenes is amazing when you're screen-sharing because it means you don't have to focus on another window while you're in the middle of something.
|
||||
|
||||
#### Window management
|
||||
|
||||
Window focus—keeping all the right things visible and everything else not visible—is definitely a huge challenge when streaming. Let's just say that I had to rotate a lot of keys in the first few months of my streaming journey!
|
||||
|
||||
There's a lot to look at, between OBS, probably some chat/moderation/events, the stream itself… you get the idea. My setup's buttons focus on the applications I use the most while streaming (they call a mixture of [wmctrl][11] and [gtk-launch][12]), and it has made things much easier to operate. I have one button for OBS, one for stream manager, and one for my featured chat dashboard (the last two are web pages packaged to make them standalone apps using [Nativefier][13]). Now my streams are more about the topics I have in mind, rather than mostly showing Alt+Tab.
|
||||
|
||||
I can absolutely imagine using this for other day-to-day applications, such as if you regularly rotate among a set of applications and want the ability to conjure one up immediately. I'm using browser tabs in a known order for this purpose, but I feel I have missed an opportunity for a productivity hack here.
|
||||
|
||||
#### The bot and the clipboard
|
||||
|
||||
I stream a bunch of different technologies, and my geeky audience asks a lot of questions and recommends a lot of tools, which is brilliant. However, that means I spent a lot of time finding and focusing on the chat window (and the text box within that window) to share links. To improve this, I switched the channel bot to [Nightbot][14], a chatbot that adds moderation and other features to a stream's chat function. Many bots are available, but I chose this one because it has API integration and buttons to help me get things into chat when I need them.
|
||||
|
||||
The first two buttons cue things up. I often paste URLs into my streams, but I don't want to risk accidentally pasting a password. So the cue button first cues up what I have in my clipboard (shout out to [Clipboard for Go][15] for the clipboard integration) and shows it to me. The other cue button reads the next line from a file I keep of things I might want to share on a stream—maybe I want to mention an event where I'm speaking that I think the crowd would like, or I know I'm going to promote a particular tool on the stream that day—and shows me what it's going to send. I can press the cue button again to see another line from the file.
|
||||
|
||||
The Send button causes the bot to "chat" the cued-up text into my channel. This is a much better setup than searching for a chat window when you are mid-spiel about a topic.
|
||||
|
||||
#### Lights and sounds
|
||||
|
||||
I'm not the only streamer with funky, changeable light colors in the background of my streaming location, and having control over them is very useful. The shelf that sits behind me has a custom groove for a strip of neopixels. My Stream Deck has buttons to turn the lights on and off and implement some color presets. Everything works over [MQTT][16], and I use the [Eclipse Paho client in Go][17] to control it all. Another button on the Stream Deck turns my video light on and off so that I can get everything set up and cue the lights when I'm ready to stream, rather than blinding myself when I'm not live. I will happily admit to flipping the LED strip colors as a sort of video meeting party trick or even when nobody is watching! Buttons to press and colorful lights… what's not to like?
|
||||
|
||||
I also have sound effects on my Stream Deck, but I haven't made cute icons for those buttons yet. Technology-wise, I'm running [CasterSoundboard][18], which supports the [Open Sound Control][19] protocol, and using the [hypebeast/osc][20] library in my application to wrangle it. I have a few different sounds; they make me (and hopefully others!) smile. I have seen some really engaging sound effects on streams, but I think I'm at a beginner stage so far!
|
||||
|
||||
#### Non-streaming buttons
|
||||
|
||||
There are not many other features on my Stream Deck, but those are the ones I use the most, by far, usually when I'm not streaming. The first is a screenshot button. I write a lot of technical documentation, and sometimes that means I need to create screenshots. Having a one-press button that captures the current window in two seconds is very useful, and I am so happy with it. The button activates the command I'd use for this:
|
||||
|
||||
|
||||
```
|
||||
/usr/bin/gnome-screenshot -w -d 2
|
||||
```
|
||||
|
||||
Finally, something I never want to part with: a microphone mute button. It mutes at the system level via [pulsemixer][21], and it shows an indicator of the device's current state. I'm writing this in 2020, when video calling is my primary human contact. Since many platforms don't have a way to hover or click to get to the mute icon, having control of my sound device like this is fabulous. Lots of video calling applications will pick up these settings and show you as muted when you are and unmuting when you want to make an important point. Sometimes the smallest things are the most life-changing!
|
||||
|
||||
### Give it a go
|
||||
|
||||
There are many features I use daily, and not just when I'm streaming. I have had a lot of fun dreaming up improvements and features for the Stream Deck and sometimes streaming while I implement them.
|
||||
|
||||
There are some features that I wouldn't want to live without now. If you're on the fence about getting a device like this, I'd recommend giving it a go. There are lots of great libraries to help you make it your own.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/stream-deck
|
||||
|
||||
作者:[Lorna Mitchell][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/lornajane
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
|
||||
[2]: https://twitch.tv/lornajanetv
|
||||
[3]: https://www.elgato.com/en/gaming/stream-deck
|
||||
[4]: https://opensource.com/sites/default/files/uploads/lorna.jpg (Lorna's video streaming setup)
|
||||
[5]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[6]: https://github.com/lornajane/streamdeck-tricks
|
||||
[7]: https://opensource.com/sites/default/files/uploads/streamdeck.jpg (Stream Deck)
|
||||
[8]: https://obsproject.com/
|
||||
[9]: https://github.com/Palakis/obs-websocket
|
||||
[10]: https://github.com/christopher-dG/go-obs-websocket
|
||||
[11]: https://en.wikipedia.org/wiki/Wmctrl
|
||||
[12]: https://developer.gnome.org/gtk3/stable/gtk-launch.html
|
||||
[13]: https://github.com/jiahaog/Nativefier
|
||||
[14]: https://nightbot.tv/
|
||||
[15]: https://github.com/atotto/clipboard
|
||||
[16]: https://mqtt.org/
|
||||
[17]: https://github.com/eclipse/paho.mqtt.golang
|
||||
[18]: https://github.com/JupiterBroadcasting/CasterSoundboard
|
||||
[19]: http://opensoundcontrol.org/osc
|
||||
[20]: https://github.com/hypebeast/go-osc
|
||||
[21]: https://pypi.org/project/pulsemixer/
|
@ -1,114 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Pretty Print JSON File in Linux Terminal)
|
||||
[#]: via: (https://itsfoss.com/pretty-print-json-linux/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
How to Pretty Print JSON File in Linux Terminal
|
||||
======
|
||||
|
||||
[JSON][1] files are awesome because they store collection of data in a human-readable format. However, reading the JSON file can be a pain if the JSON file is minified.
|
||||
|
||||
Take this for an example:
|
||||
|
||||
![Minified JSON is difficult to read][2]
|
||||
|
||||
A computer can easily read it. Even a human can still read it but if JSON file is properly formatted to display the content, it will be much easier. I mean JSON files are supposed to read like this after all:
|
||||
|
||||
![Pretty Printed JSON is easier to read][3]
|
||||
|
||||
You can use most text editor with some plugins to display it with proper formatting. However, if you are stuck to a terminal or if you want to do it in your shell script, things will be different.
|
||||
|
||||
If you got a minified file, let me show you how to pretty print the JSON file in Linux terminal.
|
||||
|
||||
### Pretty print JSON with jq command in Linux
|
||||
|
||||
[jq][4] is a command line JSON processor. You can use it to slice, filter, map and transform structured data. I am not going in details about using jq command line tool here.
|
||||
|
||||
To use jq, you need to install it first. You can use your [distribution’s package manager][5] to install it. With [universe repository enabled][6], you can install it on Ubuntu using the apt command:
|
||||
|
||||
```
|
||||
sudo apt install jq
|
||||
```
|
||||
|
||||
Once you have it installed, use it in the following manner to pretty print JSON file on the display:
|
||||
|
||||
```
|
||||
jq . sample.json
|
||||
```
|
||||
|
||||
![Pretty printed JSON file][7]
|
||||
|
||||
You may also tempt to use cat but I believe it one of the useless use of cat command.
|
||||
|
||||
```
|
||||
cat sample.json | jq
|
||||
```
|
||||
|
||||
Keep in mind that the above command will not impact the original JSON file. No changes will be written to it.
|
||||
|
||||
You probably already know [how to redirect the command output to a file in Linux][8]. You probably also know that you cannot redirect to the same file and the tee command is not guaranteed to work all the time.
|
||||
|
||||
If you want to modify the original JSON file with pretty print format, you can pipe the parsed output to a new file and then copy it to the original JSON file.
|
||||
|
||||
```
|
||||
jq . sample.json > pretty.json
|
||||
```
|
||||
|
||||
![Pretty printing JSON file in Linux Terminal][9]
|
||||
|
||||
#### Bonus: Minify a JSON file with jq command
|
||||
|
||||
Let’s take a reverse stance and minify a well formatted JSON file. To minify a JSON file, you can use the compact option -c.
|
||||
|
||||
```
|
||||
jq -c < pretty.json
|
||||
```
|
||||
|
||||
![Minified JSON file display][10]
|
||||
|
||||
You can also use cat and redirection if you want:
|
||||
|
||||
```
|
||||
cat pretty.json | jq -c
|
||||
```
|
||||
|
||||
### Using Python to pretty print JSON file in Linux
|
||||
|
||||
It’s more likely that you have Python installed on your system. If that’s the case, you can use it pretty print the JSON file in the terminal:
|
||||
|
||||
```
|
||||
python3 -m json.tool sample.json
|
||||
```
|
||||
|
||||
![Pretty printing JSON with Python][11]
|
||||
|
||||
I know there are other ways to parse JSON file and print it with proper format. You may explore them on your own but these two are sufficient to do the job which is to pretty print JSON file.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/pretty-print-json-linux/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.json.org
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/12/print-json.png?resize=759%2C253&ssl=1
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-printed-json.png?resize=696%2C538&ssl=1
|
||||
[4]: https://stedolan.github.io/jq/
|
||||
[5]: https://itsfoss.com/package-manager/
|
||||
[6]: https://itsfoss.com/ubuntu-repositories/
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-print-json-linux-terminal.png?resize=750%2C557&ssl=1
|
||||
[8]: https://itsfoss.com/save-command-output-to-file-linux/
|
||||
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-printing-json-linux-terminal.png?resize=750%2C576&ssl=1
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/12/minify-json-file-linux.png?resize=777%2C253&ssl=1
|
||||
[11]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-print-json-with-python.png?resize=777%2C557&ssl=1
|
@ -0,0 +1,70 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Make medit your next Linux terminal text editor)
|
||||
[#]: via: (https://opensource.com/article/20/12/medit)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Make medit your next Linux terminal text editor
|
||||
======
|
||||
This classic text editor offers all the basics and some exciting extra
|
||||
features that let you customize your experience.
|
||||
![Person drinking a hot drink at the computer][1]
|
||||
|
||||
There’s [XEDIT][2], jEdit, NEdit, [gedit][3], and, as it turns out, [medit][4].
|
||||
|
||||
I had not heard about medit until I started searching for editors I hadn’t yet tried, but I’m glad to have discovered it. If you’re looking for a classic gedit experience (circa Gnome 2), then medit is, probably unintentionally, an excellent and modern approximation. It’s also got many additional features, such as the ability to write plugins in Python, Lua, or C, and a means to integrate even shell scripts into its menu system. All the other usual features are here, too—a tabbed interface, an on-demand shell, indentation management, syntax highlighting, and so on.
|
||||
|
||||
### Installing medit
|
||||
|
||||
You can download medit from [mooedit.sourceforge.net][5]. It’s confirmed to work on Linux and Windows. If you’re using Linux, you may also find it in your repository. I installed my copy from [slackbuilds.org][6] on Slackware.
|
||||
|
||||
![Medit terminal showing examples of Bash script in editor][7]
|
||||
|
||||
### Using medit
|
||||
|
||||
Medit advertises itself as an editor "for programming and around programming," and in fact, started its life out as part of a larger project called [GAP (Groups, Algorithms, Programming)][8]. Most of its features are aimed at typical developer expectations. For instance, in the **Edit** menu, there are options to increase and decrease indentation, a common task for any programmer trying to indicate scope visually (and a literal requirement for Python programmers), and options to comment or uncomment blocks of text.
|
||||
|
||||
Some features can be useful for general users, too. Medit has an easy-to-use tabbed interface (both at the top of the window and as a pop-up list along the side), a side panel for quick filesystem browsing, the ability to bookmark places in a file, and so on. It also has syntax highlighting for both programming languages, as well as markup and markdown languages, so it’s a useful editor for code and prose alike.
|
||||
|
||||
### Color schemes
|
||||
|
||||
When editing plain text with no syntax associated with it or a format like Asciidoc, for which medit has no preset highlighting scheme, the editor assumes your system default. I use a dark theme, so medit displays white text on a dark gray background.
|
||||
|
||||
For syntax highlighting, though, the text becomes colorful depending on the part each word plays in its structured language. At first, I was a little frustrated at some of the choices medit made; many of the colors were too dark against my dark background to be legible, and I didn’t feel that all the important elements were unique enough. The answer to this problem, should you disagree with medit’s choices, is in **Preferences**, where you can change the color theme. I changed mine to the Tango colors, which rendered a solarized color array that stood out nicely against my dark editor background and even added color to elements that were kept white under the medit theme.
|
||||
|
||||
![Medit terminal showing examples of Bash script in editor using Tango color scheme against dark background][9]
|
||||
|
||||
### Pop-up Python
|
||||
|
||||
At the bottom of the medit window, there’s a pop-up terminal for quick access to a shell. This is a nice feature, but frankly, after you’ve experienced Emacs and [Kate][10], it feels pretty common. What surprised me about medit was its pop-up Python console, which launches from the **Tools** menu with **moo** and **gtk** modules pre-imported. In other words, when you launch medit’s Python shell, you can look through the Python and GTK modules that medit itself is partly built upon. It’s a great feature and one that might inspire you to write a plugin (the Terminal pop-up is a plugin written in Python, so you can also look through its code to get a feel for how a plugin is written).
|
||||
|
||||
### Classic editing
|
||||
|
||||
Medit is a great GTK-based editor with all the important basic features and several tantalizing extras to help inspire you to extend the application and make it your own. As it accepts C, Python, Lua, and Bash, there are several entry points for doing just that. If you’re looking for a no-nonsense editor for your writing, whether it’s code or markdown or something in between, give medit a chance.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/medit
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hot drink at the computer)
|
||||
[2]: https://opensource.com/article/20/12/xedit
|
||||
[3]: https://opensource.com/article/20/12/gedit
|
||||
[4]: http://mooedit.sourceforge.net/
|
||||
[5]: https://sourceforge.net/projects/mooedit/files/medit/
|
||||
[6]: https://slackbuilds.org/repository/14.2/development/medit
|
||||
[7]: https://opensource.com/sites/default/files/uploads/medit-31_days_medit-opensource.png (Medit terminal showing examples of Bash script in editor)
|
||||
[8]: https://www.gap-system.org/
|
||||
[9]: https://opensource.com/sites/default/files/uploads/medit-tango-colour-31_days_medit-opensource.png (Medit terminal showing examples of Bash script in editor using Tango color scheme against dark background)
|
||||
[10]: https://opensource.com/article/20/12/kate-text-editor
|
141
sources/tech/20201209 Program a simple game with Elixir.md
Normal file
141
sources/tech/20201209 Program a simple game with Elixir.md
Normal file
@ -0,0 +1,141 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Program a simple game with Elixir)
|
||||
[#]: via: (https://opensource.com/article/20/12/elixir)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
Program a simple game with Elixir
|
||||
======
|
||||
Learn Elixir by programming a "guess the number" game and comparing the
|
||||
language against ones you know.
|
||||
![A die with rainbow color background][1]
|
||||
|
||||
To you learn a new programming language, it's good to focus on the things most programming languages have in common:
|
||||
|
||||
* Variables
|
||||
* Expressions
|
||||
* Statements
|
||||
|
||||
|
||||
|
||||
These concepts are the basis of most programming languages. Because of these similarities, once you know one programming language, you can start figuring another one out by recognizing its differences.
|
||||
|
||||
Another good tool for learning a new language is starting with a standard program. This allows you to focus on the language, not the program's logic. We're doing that in this article series using a "guess the number" program, in which the computer picks a number between one and 100 and asks you to guess it. The program loops until you guess the number correctly.
|
||||
|
||||
The "guess the number" program exercises several concepts in programming languages:
|
||||
|
||||
* Variables
|
||||
* Input
|
||||
* Output
|
||||
* Conditional evaluation
|
||||
* Loops
|
||||
|
||||
|
||||
|
||||
It's a great practical experiment to learn a new programming language.
|
||||
|
||||
### Guess the number in Elixir
|
||||
|
||||
The [Elixir][2] programming language is a dynamically typed functional language designed for building stable and maintainable applications. It runs on top of the same virtual machine as [Erlang][3] and shares many of its strengths—but with slightly easier syntax.
|
||||
|
||||
You can explore Elixir by writing a version of the "guess the number" game.
|
||||
|
||||
Here is my implementation:
|
||||
|
||||
|
||||
```
|
||||
defmodule Guess do
|
||||
def guess() do
|
||||
random = Enum.random(1..100)
|
||||
IO.puts "Guess a number between 1 and 100"
|
||||
Guess.guess_loop(random)
|
||||
end
|
||||
def guess_loop(num) do
|
||||
data = IO.read(:stdio, :line)
|
||||
{guess, _rest} = Integer.parse(data)
|
||||
cond do
|
||||
guess < num ->
|
||||
IO.puts "Too low!"
|
||||
guess_loop(num)
|
||||
guess > num ->
|
||||
IO.puts "Too high!"
|
||||
guess_loop(num)
|
||||
true ->
|
||||
IO.puts "That's right!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Guess.guess()
|
||||
```
|
||||
|
||||
To assign a value to a variable, list the variable's name followed by the `=` sign. For example, the statement `random = 0` assigns a zero value to the `random` variable.
|
||||
|
||||
The script starts by defining a **module**. In Elixir, only modules can have named functions in them.
|
||||
|
||||
The next line defines the function that will serve as the entry point, `guess()`, which:
|
||||
|
||||
* Calls the `Enum.random()` function to get a random integer
|
||||
* Prints the game prompt
|
||||
* Calls the function that will serve as the loop
|
||||
|
||||
|
||||
|
||||
The rest of the game logic is implemented in the `guess_loop()` function.
|
||||
|
||||
The `guess_loop()` function uses [tail recursion][4] to loop. There are several ways to do looping in Elixir, but using tail recursion is a common one. The last thing `guess_loop()` does is call _itself_.
|
||||
|
||||
The first line in `guess_loop()` reads the input from the user. The next line uses `parse()` to convert the input to an integer.
|
||||
|
||||
The `cond` statement is Elixir's version of a multi-branch statement. Unlike `if/elif` or `if/elsif` in other languages, Elixir does not treat the first nor the last branch in a different way.
|
||||
|
||||
This `cond` statement has a three-way branch: The guess can be smaller, bigger, or equal to the random number. The first two options output the inequality's direction and then tail-call `guess_loop()`, looping back to the beginning. The last option outputs `That's right`, and the function finishes.
|
||||
|
||||
### Sample output
|
||||
|
||||
Now that you've written your Elixir program, you can run it to play the "guess the number" game. Every time you run the program, Elixir will pick a different random number, and you can guess until you find the correct number:
|
||||
|
||||
|
||||
```
|
||||
$ elixir guess.exs
|
||||
Guess a number between 1 and 100
|
||||
50
|
||||
Too high
|
||||
30
|
||||
Too high
|
||||
20
|
||||
Too high
|
||||
10
|
||||
Too low
|
||||
15
|
||||
Too high
|
||||
13
|
||||
Too low
|
||||
14
|
||||
That's right!
|
||||
```
|
||||
|
||||
This "guess the number" game is a great introductory program for learning a new programming language because it exercises several common programming concepts in a pretty straightforward way. By implementing this simple game in different programming languages, you can demonstrate some core concepts of the languages and compare their details.
|
||||
|
||||
Do you have a favorite programming language? How would you write the "guess the number" game in it? Follow this article series to see examples of other programming languages that might interest you.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/elixir
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/dice_tabletop_board_gaming_game.jpg?itok=y93eW7HN (A die with rainbow color background)
|
||||
[2]: https://elixir-lang.org/
|
||||
[3]: https://www.erlang.org/
|
||||
[4]: https://en.wikipedia.org/wiki/Tail_call
|
@ -0,0 +1,173 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Practice coding in Groovy by writing a game)
|
||||
[#]: via: (https://opensource.com/article/20/12/groovy)
|
||||
[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
|
||||
|
||||
Practice coding in Groovy by writing a game
|
||||
======
|
||||
Groovy streamlines Java's syntax, making it an easy language for
|
||||
experienced Java coders to adopt.
|
||||
![Business woman on laptop sitting in front of window][1]
|
||||
|
||||
You see the same basic concepts in most programming languages, such as:
|
||||
|
||||
* Variables: Places where information is stored
|
||||
* Expressions: Ways to calculate things
|
||||
* Statements: How state changes are expressed in a program
|
||||
|
||||
|
||||
|
||||
Once you understand these concepts, you can start figuring out what makes one language different from another. For example, most languages have a "way of doing things" supported by their design, and those ways can be quite different from one program to another. These include modularity (grouping related functionality together), declarative vs. imperative, object-orientation, low- vs. high-level syntactic features, and so on.
|
||||
|
||||
An example that is familiar to many programmers is "ceremony," that is, the amount of work required to set the scene before tackling a problem. The Java programming language is said to have a significant ceremony requirement stemming from its design, which requires all code to be defined within a class.
|
||||
|
||||
But back to the basics. Programming languages usually share similarities like the ones mentioned above, so once you know one, you can start learning the basics of another to appreciate its differences. One way to expand on the languages you know is by using a basic test program to begin learning. That's what we're doing in this series of articles, using a "guess the number" program, in which the computer picks a number between one and 100 and asks you to guess it. The program loops until you guess the correct answer.
|
||||
|
||||
The "guess the number" program exercises several concepts in programming languages:
|
||||
|
||||
* Variables
|
||||
* Input
|
||||
* Output
|
||||
* Conditional evaluation
|
||||
* Loops
|
||||
|
||||
|
||||
|
||||
It's also a great practical experiment to learn a new programming language.
|
||||
|
||||
### Guess the number in Groovy
|
||||
|
||||
[Groovy][2] is dynamically typed, feels like a scripting language, and has good support for interactive use. It was designed to leverage the Java Virtual Machine (JVM) ecosystem and has a high level of source compatibility with Java, along with its streamlined and high-level syntax features.
|
||||
|
||||
Here is my implementation of the "guess the number" game in Groovy (with line numbers so I can review some of the specific features):
|
||||
|
||||
|
||||
```
|
||||
1 int randomNumber = (new [Random][3]()).nextInt(100) + 1
|
||||
|
||||
2 println "the secret number is $randomNumber"
|
||||
|
||||
3 print 'Guess a number: '
|
||||
4 [System][4].in.withReader { reader ->
|
||||
5 [String][5] response
|
||||
6 while (response = reader.readLine()) {
|
||||
7 if (! response.isNumber())
|
||||
8 print "that's not a number! try again: "
|
||||
9 else {
|
||||
10 int guess = response as [Integer][6]
|
||||
11 if (guess < randomNumber)
|
||||
12 print 'too low, try again: '
|
||||
13 else if (guess > randomNumber)
|
||||
14 print 'too high, try again: '
|
||||
15 else {
|
||||
16 println "that's right"
|
||||
17 break
|
||||
18 }
|
||||
19 }
|
||||
20 }
|
||||
21 }
|
||||
```
|
||||
|
||||
For those familiar with Java or C, the syntax will seem broadly familiar (unlike in Python, for example). In Groovy statements such as `if-then-else` or `while`, the `then`, `else`, and `while` parts take either a statement or a group of statements enclosed within `{` and `}`. Java programmers will note that Groovy provides streamlined support for scripting—no need for wrapping the program in a class definition.
|
||||
|
||||
Groovy is object-oriented and has access to the Java standard library. In line 1 of my code, to generate a random number, it creates a new instance of the Random class and calls the nextInt() method on it with an argument of 100, which will give a number between 0 and 99; and so we add one to this result.
|
||||
|
||||
One more thing to note: Groovy doesn't require semicolons to terminate lines when it can figure out the end of a statement from the presence of a newline.
|
||||
|
||||
The second statement prints out the number that was generated, for debugging purposes. Worth mentioning here is Groovy's active efforts to hide Java ceremony; in Java, this would be written:
|
||||
|
||||
|
||||
```
|
||||
`System.out.println("The secret number is " + randomNumber);`
|
||||
```
|
||||
|
||||
The Groovy compiler takes away the need to prepend `System.out` in front of `println`. Groovy also makes parentheses in method invocations optional as long as the arguments can be clearly identified (but a method that takes no arguments still needs the `()` following the method name).
|
||||
|
||||
Another cool Groovy feature, visible in line 2, is the use of a `GString`. Note the `$` in front of `randomNumber` within the string, which causes the value of the variable `randomNumber` to be interpolated into the string. An expression can be interpolated using `${ }`.
|
||||
|
||||
In line 3, Groovy permits the use of single quotes instead of double quotes to delineate a `String` literal. Double quotes are required for a `GString`. This line prints a prompt for the person running the script.
|
||||
|
||||
I want to be able to read input from the console (typically a terminal window). Java defines the `System` static class and the `in` static field as a way to get at stuff the user is typing in the console. Statement 4 calls the `withReader` method on the `System.in` field to set up and tear down a line-oriented String reader—another example of Groovy's streamlining. `withReader` takes a closure as its argument—a kind of "anonymous code block," similar to a lambda in Java. When `withReader` calls the supplied closure, it passes the reader as an argument to the closure. The corresponding parameter is defined in the closure with the fragment `reader ->`.
|
||||
|
||||
This closure business is a really interesting feature in Groovy. Although it's similar to a lambda, it does not have lambda's limitations, such as only being able to refer to final or equivalent-to-final variables in the enclosing scope, so there's no need to worry much about the definition of `randomNumber` external to the closure.
|
||||
|
||||
The closure, which begins with the `{ reader ->` on line 4 and ends with the `}` on line 21, is the chunk of code that processes the user's input.
|
||||
|
||||
Within that closure is code that mostly looks familiar. Line 5 declares the `String` variable `response` (which is local to the closure). Line 6 starts a `while` loop that iterates as long as the user continues to guess, terminating if the line is empty or the user signals an end-of-file (say with a **Ctrl+D** in a Linux terminal window). This `while` loop ends with the `}` on line 20.
|
||||
|
||||
Note the expression tested by the `while` loop is:
|
||||
|
||||
|
||||
```
|
||||
`response = reader.readLine()`
|
||||
```
|
||||
|
||||
Groovy has an extended definition of "truth." An expression that yields `true` is true, but so is an expression that yields a non-zero numeric value, non-empty string value, or non-null value. This expression will yield an empty string if the user presses return, or a `null` if the user types a **Ctrl+D**, which `System.in` turns into a `null`.
|
||||
|
||||
Lines 7 and 8 check to see if the user entered a `String` value that can be converted to a number and will complain if not. Instances of the Groovy `String` class (i.e., all Strings) have a method called `isNumber()` that can be used for this kind of test. Compare this usage to the typical Java approach, which uses a `try-catch` block.
|
||||
|
||||
Lines 9 through 19 process the value entered by the user. Line 10 converts the `String` value entered to an `Integer` using Groovy's `as` keyword, which can handle many coercions and conversions. The rest of the code tests whether the converted integer value is too low, too high, or just right. Note again the use of single quotes vs. double quotes, particularly in the `println` call on line 19, where double quotes are used to delimit the `String` literal because of the single quote within.
|
||||
|
||||
### Sample output
|
||||
|
||||
How well did this do in demonstrating the concepts I outlined earlier?
|
||||
|
||||
* Variables: Yup, Groovy has those; see the `int` variables and `String` variables.
|
||||
* Input: I used `System.in` as predefined console input and a reader to get values from that.
|
||||
* Output: I used Groovy's `println` (Java's `System.out.println`) to print messages on the console.
|
||||
* Conditional evaluation: I explored Groovy's `if-then-else` as well as Groovy truth.
|
||||
* Loops: I used these in Groovy's `while` loop.
|
||||
|
||||
|
||||
|
||||
I also used some Java standard library functionality, such as the `isNumeric()` method on `String` instances and the `withReader()` method on `System.in`. I used a closure, kind of like a Java lambda.
|
||||
|
||||
Run the program to play the game:
|
||||
|
||||
|
||||
```
|
||||
$ groovy guess.groovy
|
||||
the secret number is 29
|
||||
Guess a number: 50
|
||||
too high, try again: 25
|
||||
too low, try again: 37
|
||||
too high, try again: 31
|
||||
too high, try again: 28
|
||||
too low, try again: 29
|
||||
that's right
|
||||
$
|
||||
```
|
||||
|
||||
I feel I should mention that the optimal way to play this game is to use a binary search strategy: Calculate in your head the mean of the most recent "too high" and the most recent "too low" and use that as your next guess.
|
||||
|
||||
One thing I didn't cover is comments. Like Java, Groovy comments can begin with a `//` and run to the end of the line or can be wrapped in `/* */`. I could comment out the debug `println` with a `//` in front to make it harder to cheat.
|
||||
|
||||
### Learn more
|
||||
|
||||
If you want to learn Groovy, start with the official [Groovy website][2]. I find [Hubert A. Klein Ikkink's musings][7] on Groovy, Grails, and Java to be extremely worthwhile. There are also many fine books about Groovy; even if they are somewhat dated, they are still worth reading. I like Venkat Subramaniam's [_Programming Groovy 2: Dynamic productivity for the Java developer_][8].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/groovy
|
||||
|
||||
作者:[Chris Hermansen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/clhermansen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-concentration-focus-windows-office.png?itok=-8E2ihcF (Woman using laptop concentrating)
|
||||
[2]: https://groovy-lang.org/
|
||||
[3]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+random
|
||||
[4]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
|
||||
[5]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+integer
|
||||
[7]: https://www.mrhaki.com/
|
||||
[8]: https://www.bookdepository.com/Programming-Groovy-2-Venkat-Subramaniam/9781937785307
|
@ -0,0 +1,147 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Set up a hyperconverged infrastructure with open source tools)
|
||||
[#]: via: (https://opensource.com/article/20/12/hyperconverged-infrastructure)
|
||||
[#]: author: (Sahina Bose https://opensource.com/users/sahina)
|
||||
|
||||
Set up a hyperconverged infrastructure with open source tools
|
||||
======
|
||||
Run a full-featured virtualization environment with oVirt and Gluster
|
||||
and without burning a hole in your pocket.
|
||||
![Computer laptop in space][1]
|
||||
|
||||
A modern infrastructure's needs are ever-growing. As demand grows for scaling up applications, our existing servers and storage are no longer enough. This is the point when most businesses look at setting up a virtualized environment on-premises or turning to public cloud infrastructure. But the cost of setting up your own environment or running it on the public cloud can be daunting.
|
||||
|
||||
Fortunately, it is entirely possible to run a full-featured virtualization environment with completely open source products without burning a hole in your pocket.
|
||||
|
||||
A hyperconverged environment is one where compute, storage, and network resources are all on the same servers, managed by a single interface. As I will show in this article, you can run a full-featured virtualized infrastructure with optimal use of servers by using [oVirt][2] and [Gluster][3] to deploy a hyperconverged solution.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
You will need the following hardware infrastructure:
|
||||
|
||||
* Three servers with:
|
||||
* 32GB RAM or more
|
||||
* Minimum 256GB storage (for anything more than a proof of concept, you will need more storage, think in terabytes)
|
||||
* Dual network interface controller (NIC) and at least one 10GiB port
|
||||
* Network switch
|
||||
* Configured media access control (MAC) reservation and Domain Name System (DNS) entry
|
||||
|
||||
|
||||
|
||||
The software components you need for this solution are:
|
||||
|
||||
* [**oVirt**][2], an open source virtualization software management solution with all the enterprise features you need, such as host, virtual machine (VM) and network management, high availability, and live migration
|
||||
* [**GlusterFS**][3], an open source scalable distributed storage that can run highly available petabyte-scale storage on commodity hardware.
|
||||
|
||||
|
||||
|
||||
### How it works
|
||||
|
||||
These two open source solutions work together to provide a hyperconverged solution. Each server provides both hypervisor and storage capabilities, with the VM disk images stored on the Gluster volume.
|
||||
|
||||
The Gluster volume allows storage from multiple servers to present as a single, unified namespace to the client. In this solution, the Gluster volume is configured from storage on the three servers as a replica-3 volume, which means every bit of data that's written is replicated to two other servers to provide redundancy and resiliency against server outages.
|
||||
|
||||
Gluster volumes can also be configured to run as [arbiter volumes][4], which have lower storage requirements than replica-3 volumes, as data is copied to only one other server while metadata is written on a third server. Both of these volume configurations ensure that the VMs continue to run without downtime if one of the servers goes down.
|
||||
|
||||
[Libvirt][5] and [qemu-kvm][6] are used to create the VM images and run them on the servers. The oVirt engine manages creating, scheduling, and monitoring of VMs. Since the storage is shared across all three servers, the VMs can run on any of the three servers, allowing for live migration and high availability.
|
||||
|
||||
oVirt has two main components:
|
||||
|
||||
* **oVirt Engine** is a Java-based web application that manages the server and virtual machines. The engine can either run on a standalone server or a VM within the same infrastructure that it manages.
|
||||
* **Vdsm** is a Python service that runs on every server and interacts with the engine and the subcomponents on the server.
|
||||
|
||||
|
||||
|
||||
In the hyperconverged deployment, the oVirt engine runs as a VM managing the servers that it runs on. In this mode, it's also known as "Hosted Engine."
|
||||
|
||||
![Hosted Engine architecture][7]
|
||||
|
||||
(Sahina Bose, [CC BY-SA 4.0][8])
|
||||
|
||||
### Putting it all together
|
||||
|
||||
With so many components involved, you may find the thought of setting everything up daunting. However, installation is easy with the oVirt Node ISO, which contains all the required packages and a [Cockpit][9]-based installation wizard that guides you through the steps.
|
||||
|
||||
1. Download and install the latest [oVirt Node ISO][10] on all three servers.
|
||||
|
||||
2. Navigate to the Cockpit server administration URL on any of the servers at `https://<server1>:9090`.
|
||||
|
||||
3. Follow the steps for the Hosted Engine installation with Gluster.
|
||||
|
||||
![Hosted Engine installation UI][11]
|
||||
|
||||
(Sahina Bose, [CC BY-SA 4.0][8])
|
||||
|
||||
These steps guide you through:
|
||||
|
||||
* Setting up networks and hosts
|
||||
|
||||
![Network and hosts setup][12]
|
||||
|
||||
(Sahina Bose, [CC BY-SA 4.0][8])
|
||||
|
||||
A minimum of three hosts is required to run a highly available environment. The wizard prompts you to separate the storage network from the management network.
|
||||
|
||||
* Setting up the Gluster volume
|
||||
|
||||
![Setting up the Gluster volume][13]
|
||||
|
||||
(Sahina Bose, [CC BY-SA 4.0][8])
|
||||
|
||||
By default, three Gluster volumes are created to hold the VM disk images. The engine volume is dedicated to holding the Hosted Engine disk image. Separating this helps with easy backup and recovery.
|
||||
|
||||
![Engine volume setup][14]
|
||||
|
||||
(Sahina Bose, [CC BY-SA 4.0][8])
|
||||
|
||||
Most of the configuration is automated, but you need to ensure you provide the underlying disk information to the user interface.
|
||||
|
||||
* Deploying the oVirt engine as Hosted Engine
|
||||
|
||||
![Engine volume deployment][15]
|
||||
|
||||
(Sahina Bose, [CC BY-SA 4.0][8])
|
||||
|
||||
Once the storage has been configured, you must provide the details for the Hosted Engine VM—the fully qualified domain name ([FQDN][16]) and the MAC address reserved for the VM—to complete the deployment.
|
||||
|
||||
|
||||
|
||||
|
||||
### Learn more
|
||||
|
||||
It's this simple to set up a fully functional hyperconverged environment with a management interface you can use to manage and monitor your virtual machines, storage, and network. For further information, please refer to the [oVirt-Gluster hyperconvergence guide][17].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/hyperconverged-infrastructure
|
||||
|
||||
作者:[Sahina Bose][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/sahina
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_space_graphic_cosmic.png?itok=wu493YbB (Computer laptop in space)
|
||||
[2]: https://www.ovirt.org/
|
||||
[3]: https://www.gluster.org/
|
||||
[4]: https://docs.gluster.org/en/v3/Administrator%20Guide/arbiter-volumes-and-quorum/
|
||||
[5]: https://en.wikipedia.org/wiki/Libvirt
|
||||
[6]: https://en.wikipedia.org/wiki/QEMU
|
||||
[7]: https://opensource.com/sites/default/files/uploads/ovirt_hostedengine.jpg (Hosted Engine architecture)
|
||||
[8]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[9]: https://opensource.com/article/20/11/cockpit-server-management
|
||||
[10]: https://www.ovirt.org/download/node.html
|
||||
[11]: https://opensource.com/sites/default/files/uploads/ovirt_hostedenginesetup.png (Hosted Engine installation UI)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/ovirt_networks-hosts-setup.png (Network and hosts setup)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/ovirt_gluster-setup.png (Setting up the Gluster volume)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/ovirt_engine-volume.png (Engine volume setup)
|
||||
[15]: https://opensource.com/sites/default/files/blocks/ovirt_engine-volume-deploy.png (Engine volume deployment)
|
||||
[16]: https://en.wikipedia.org/wiki/Fully_qualified_domain_name
|
||||
[17]: https://www.ovirt.org/documentation/gluster-hyperconverged/Gluster_Hyperconverged_Guide.html
|
@ -0,0 +1,67 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Why Java developers love the jEdit text editor)
|
||||
[#]: via: (https://opensource.com/article/20/12/jedit)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Why Java developers love the jEdit text editor
|
||||
======
|
||||
This editor packs the power of Java and offers plenty of plugins to
|
||||
streamline your workflow.
|
||||
![Person drinking a hot drink at the computer][1]
|
||||
|
||||
Java is a powerful language. Maybe because it’s often seen as an "industrial-strength" tool, you might not expect it to be the foundation of a text editor. After all, text editing is almost too easy for such power. In fact, in most modern programming toolkits, the component accepting text entry is a pre-programmed widget. Using a Java toolkit, a simple text editor can be written in about 100 lines of code. So what can [jEdit][2] possibly offer to justify its existence?
|
||||
|
||||
Well, quite a lot, actually! The jEdit application is a refreshing reminder of just how practical and useful Java can be for even everyday desktop apps. It deftly demonstrates the dynamism of its foundational technology, and ever true to Java’s enduring promise, it does so on _all_ platforms.
|
||||
|
||||
### Installing jEdit
|
||||
|
||||
jEdit is written in Java, so it’s available for any platform. [Download it][3] in a generic installer or in a custom installer for the OS of choice. Once it’s downloaded (it’s small, so it won’t take long), run the installer.
|
||||
|
||||
If you don’t have Java installed, learn how to install Java on [Linux][4], [Mac, or Windows][5].
|
||||
|
||||
### Using jEdit
|
||||
|
||||
The way you edit text in jEdit is the same as editing text in any desktop text editor. If you’ve used one, you’ve basically used jEdit; all the common keyboard shortcuts and conventions apply. There are also some features commonly aimed at coders—line numbering, folding (in which sections of text are hidden so you can focus on other sections), and syntax highlighting.
|
||||
|
||||
But imagine, for a moment, text editors on a spectrum from [Vim simplicity][6] to [Emacs complexity][7], and you’ll find jEdit happily making its home alongside Emacs. While the editing component is typical of any desktop editing app, jEdit’s additional features include plugins, macros that you can record live during your editing session, features specific to certain editing modes, buffer options, and more. This is an editor that actively encourages you to make it your own.
|
||||
|
||||
There are three places you can go for jEdit customization: buffer options, global options, and the plugins manager.
|
||||
|
||||
Buffer options (in the Utilities menu) allow you to adjust settings associated with your current document. Usually, jEdit auto-detects the appropriate mode to use for what you’re doing. For instance, writing XML triggers jEdit’s XML highlighting. Sometimes, though, you want to override what jEdit has detected or failed to detect. You can also turn on Explicit Folding mode, which allows you to manually define sections of text you want jEdit to treat as foldable sections.
|
||||
|
||||
Global options (in the Utilities menu) offer dozens of preferences that get treated as jEdit’s defaults. This can include anything from its appearance to custom shortcuts.
|
||||
|
||||
Plugins extend jEdit in ways its developers, literally, never intended. Plugins offer ways of working that just aren’t "normal" for jEdit, but that just might transform a laborious task into something easy or even fun. It practically transformed XML workflow with its excellent XML parsing, its _Outline_ plugin available for its dockable _Sidekick_ panel, and XSLT integration. If I were not already using Netbeans for Java code, I can imagine using jEdit instead.
|
||||
|
||||
### jEdit for programmers
|
||||
|
||||
Which text editor you choose depends on what you intend to do in your editor. This one calls itself the "programmer’s text editor," and I feel it’s a very strong contender for serious Java and XML work. However, it doesn’t have quite the same feature set when editing Lua code and Bash scripts. Compared to something like Emacs, for instance, jEdit’s code folding is less flexible (I couldn’t get it to fold a Lua function without additional markup). While it does have a rich plugin selection, I was unable to find anything particularly persuasive for work in AsciiDoc and other non-code formats.
|
||||
|
||||
The most appealing feature of jEdit, for me, is its foundation in Java. Because it runs in a JVM, you can be confident that you can use it regardless of your platform and possibly regardless of whether you have permission to install applications outside your own home directory. Java is a popular and active language, so jEdit’s features and plugins are well-maintained.
|
||||
|
||||
You should try jEdit if you’re a fan of consistency, or a Java developer, or just an XML geek trying desperately to get out of oXygen. It’s easy to get started, and it’s a lot of fun to explore.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/jedit
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hot drink at the computer)
|
||||
[2]: http://jedit.org
|
||||
[3]: http://www.jedit.org/index.php?page=download
|
||||
[4]: https://opensource.com/article/19/11/install-java-linux
|
||||
[5]: http://adoptopenjdk.org
|
||||
[6]: https://opensource.com/article/20/12/vi-text-editor
|
||||
[7]: https://opensource.com/article/20/12/emacs
|
@ -0,0 +1,191 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (zhangxiangping)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (An attempt at implementing char-rnn with PyTorch)
|
||||
[#]: via: (https://jvns.ca/blog/2020/11/30/implement-char-rnn-in-pytorch/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
用PyTorch实现char-rnn
|
||||
======
|
||||
|
||||
你好!在过去的几周里,我花了很多时间用PyTorch实现了一个[char-rnn][1]的版本。我以前从未训练过神经网络,所以这可能是一个有趣的开始。
|
||||
|
||||
这个想法(来自[The Unreasonable Effectiveness of Recurrent Neural Networks][1])可以让你在文本上训练一个基于字符的循环神经网络,并得到一些出乎意料的结果。
|
||||
|
||||
不过,虽然没有得到我想要的结果,但是我还是想分享一些示例代码和结果,希望对其他开始尝试使用PyTorch和RNNs的人有帮助。
|
||||
|
||||
这是Jupyter notebook格式的代码:[char-rnn in PyTorch.ipynb][2]。你可以点击这个网页最上面那个按钮Open in Colab,就可以在Google的Colab服务中打开,并使用免费的GPU进行训练。所有的东西加起来大概有75行代码,我将在这篇博文中尽可能地详细解释。
|
||||
|
||||
### 第一步:准备数据
|
||||
|
||||
首先,我们要下载数据。我使用的是古登堡项目中的这个数据:[Hans Christian Anderson’s fairy tales][3]。
|
||||
|
||||
```
|
||||
!wget -O fairy-tales.txt
|
||||
```
|
||||
|
||||
这个是准备数据的代码。我使用fastai库中的Vocab类进行数据处理,它能将一堆字母转换成“词表”,然后用这个“词表”把字母变成数字。
|
||||
|
||||
之后我们就得到了一大串数字(`训练集`),我们可以在这上面训练我们的模型。
|
||||
|
||||
```
|
||||
from fastai.text import *
|
||||
text = unidecode.unidecode(open('fairy-tales.txt').read())
|
||||
v = Vocab.create((x for x in text), max_vocab=400, min_freq=1)
|
||||
training_set = torch.Tensor(v.numericalize([x for x in text])).type(torch.LongTensor).cuda()
|
||||
num_letters = len(v.itos)
|
||||
```
|
||||
|
||||
### 第二步:定义模型
|
||||
|
||||
这个是Pytorch中LSTM类的封装。除了封装LSTM类以外,它还做了三件事:
|
||||
|
||||
1. 对输入向量进行one-hot编码,使得他们具有正确的维度。
|
||||
2. 在LSTM层后一层添加一个线性变换,因为LSTM输出的是一个长度为`hidden_size`的向量,我们需要的是一个长度为`input_size`的向量这样才能把它变成一个字符。
|
||||
3. 把LSTM隐藏层的输出向量(实际上有2个向量)保存成实例变量,然后在每轮运行结束后执行`.detach()`函数。(我很难解释清`.detach()`的作用,但我的理解是,它在某种程度上“结束”了模型的求导计算(译者注:detach()函数是将该张量的requires_grad参数设置为False,即反向传播到该张量就结束。))
|
||||
|
||||
```
|
||||
class MyLSTM(nn.Module):
|
||||
def __init__(self, input_size, hidden_size):
|
||||
super().__init__()
|
||||
self.lstm = nn.LSTM(input_size, hidden_size, batch_first=True)
|
||||
self.h2o = nn.Linear(hidden_size, input_size)
|
||||
self.input_size=input_size
|
||||
self.hidden = None
|
||||
|
||||
def forward(self, input):
|
||||
input = torch.nn.functional.one_hot(input, num_classes=self.input_size).type(torch.FloatTensor).cuda().unsqueeze(0)
|
||||
if self.hidden is None:
|
||||
l_output, self.hidden = self.lstm(input)
|
||||
else:
|
||||
l_output, self.hidden = self.lstm(input, self.hidden)
|
||||
self.hidden = (self.hidden[0].detach(), self.hidden[1].detach())
|
||||
|
||||
return self.h2o(l_output)
|
||||
```
|
||||
|
||||
这个代码还做了一些比较神奇但是不太明显的功能。如果你的输入是一个向量(比如[1,2,3,4,5,6]),对应六个字母,那么我的理解是`nn.LSTM`会在内部使用沿时间反向传播[backpropagation through time][4]更新隐藏向量6次。
|
||||
|
||||
### 第三步:编写训练代码
|
||||
|
||||
模型不会自己训练自己的!
|
||||
|
||||
我最开始的时候尝试用`fastai`库中的一个helper类(也是PyTorch中的封装)。我有点疑惑因为我不知道它在做什么,所以最后我自己编写了模型训练代码。
|
||||
|
||||
下面这些代码(epoch()方法)就是有关于一轮训练过程的基本信息。基本上就是重复做下面这几件事情:
|
||||
1. 往RNN模型中传入一个字符串,比如`and they ought not to teas`。(要以数字向量的形式传入)
|
||||
2. 得到下一个字母的预测结果。
|
||||
3. 计算RNN模型预测结果和真实的下一个字母之间的损失函数。(`e`,因为tease是以`e`结尾的)
|
||||
4. 计算梯度。(用`loss.backward()`函数)
|
||||
5. 沿着梯度下降的方向修改模型中参数的权重。(用`self.optimizer.step()`函数)
|
||||
|
||||
```
|
||||
class Trainer():
|
||||
def __init__(self):
|
||||
self.rnn = MyLSTM(input_size, hidden_size).cuda()
|
||||
self.optimizer = torch.optim.Adam(self.rnn.parameters(), amsgrad=True, lr=lr)
|
||||
def epoch(self):
|
||||
i = 0
|
||||
while i < len(training_set) - 40:
|
||||
seq_len = random.randint(10, 40)
|
||||
input, target = training_set[i:i+seq_len],training_set[i+1:i+1+seq_len]
|
||||
i += seq_len
|
||||
# forward pass
|
||||
output = self.rnn(input)
|
||||
loss = F.cross_entropy(output.squeeze()[-1:], target[-1:])
|
||||
# compute gradients and take optimizer step
|
||||
self.optimizer.zero_grad()
|
||||
loss.backward()
|
||||
self.optimizer.step()
|
||||
```
|
||||
|
||||
### 使用`nn.LSTM`沿着时间反向传播,不要自己写代码。
|
||||
|
||||
开始的时候我自己写的代码,每次传一个字母到LSTM层中,之后定期计算导数,就像下面这样:
|
||||
|
||||
```
|
||||
for i in range(20):
|
||||
input, target = next(iter)
|
||||
output, hidden = self.lstm(input, hidden)
|
||||
loss = F.cross_entropy(output, target)
|
||||
hidden = hidden.detach()
|
||||
self.optimizer.zero_grad()
|
||||
loss.backward()
|
||||
self.optimizer.step()
|
||||
```
|
||||
|
||||
这段代码每次传入一个字母,并且在最后训练了一次。这个步骤就被称为沿时间反向传播[backpropagation through time][4],Karpathy在他的博客中就是用这种方法。
|
||||
|
||||
这个方法有些用处,我编写的损失函数开始能够下降一段时间,但之后就会出现峰值。我不知道为什么会出现这种现象,但之后我改为一次传入20个字符之后,再进行反向传播,情况就变好了。
|
||||
|
||||
### 第四步:训练模型!
|
||||
|
||||
我在同样的数据上重复执行了这个训练代码大概300次,直到模型开始输出一些看起来像英文的文本。差不多花了一个多小时吧。
|
||||
|
||||
这种情况下我也不关注模型是不是过拟合了,但是如果你在真实场景中训练模型,应该要在验证集上验证你的模型。
|
||||
|
||||
### 第五步:生成输出!
|
||||
|
||||
最后一件要做的事就是用这个模型生成一些输出。我写了一个helper方法从这个训练好的模型中生成文本(`make_preds`和`next_pred`)。这里主要是把向量的维度对齐,重要的一点是:
|
||||
|
||||
```
|
||||
output = rnn(input)
|
||||
prediction_vector = F.softmax(output/temperature)
|
||||
letter = v.textify(torch.multinomial(prediction_vector, 1).flatten(), sep='').replace('_', ' ')
|
||||
```
|
||||
|
||||
基本上做的事情就是这些:
|
||||
1. RNN层为字母表中的每一个字母或者符号输出一个数值向量(`output`)。
|
||||
2. 这个输出向量**并不是**一个概率的向量,所以需要`F.softmax(output/temperature)`操作,将其转换为概率值(也就是所有数值加起来和为1)。`temperature`某种程度上控制了对更高概率的权重,在限制范围内,如果设置temperature=0.0000001,它将始终选择概率最高的字母。
|
||||
3. `torch.multinomial(prediction_vector)`用于获取概率向量,并使用这些概率在向量中选择一个索引(如12)。
|
||||
4. `v.textify`把“12”转换为字母。
|
||||
|
||||
如果我们想要处理的文本长度为300,那么只需要重复这个过程300次就可以了。
|
||||
If we want 300 characters worth of text, we just repeat this process 300 times.
|
||||
|
||||
### 结果!
|
||||
|
||||
我把预测函数中的参数设置为`temperature = 1`得到了下面的这些由模型生成的结果。看起来有点像英语,这个结果已经很不错了,因为这个模型要从头开始“学习”英语,并且是在字符序列的级别上进行学习的。
|
||||
|
||||
虽然这些话没有什么_含义_,但我们也不知道到底想要得到什么输出。
|
||||
|
||||
> “An who was you colotal said that have to have been a little crimantable and beamed home the beetle. “I shall be in the head of the green for the sound of the wood. The pastor. “I child hand through the emperor’s sorthes, where the mother was a great deal down the conscious, which are all the gleam of the wood they saw the last great of the emperor’s forments, the house of a large gone there was nothing of the wonded the sound of which she saw in the converse of the beetle. “I shall know happy to him. This stories herself and the sound of the young mons feathery in the green safe.”
|
||||
>
|
||||
> “That was the pastor. The some and hand on the water sound of the beauty be and home to have been consider and tree and the face. The some to the froghesses and stringing to the sea, and the yellow was too intention, he was not a warm to the pastor. The pastor which are the faten to go and the world from the bell, why really the laborer’s back of most handsome that she was a caperven and the confectioned and thoughts were seated to have great made
|
||||
|
||||
下面这些结果是当`temperature=0.1`时生成的,它选择字符的方式更接近于“每次都选择出现概率最高的字符”。这就使得输出结果有很多是重复的。
|
||||
|
||||
> ole the sound of the beauty of the beetle. “She was a great emperor of the sea, and the sun was so warm to the confectioned the beetle. “I shall be so many for the beetle. “I shall be so many for the beetle. “I shall be so standen for the world, and the sun was so warm to the sea, and the sun was so warm to the sea, and the sound of the world from the bell, where the beetle was the sea, and the sound of the world from the bell, where the beetle was the sea, and the sound of the wood flowers and the sound of the wood, and the sound of the world from the bell, where the world from the wood, and the sound of the
|
||||
|
||||
这段输出对这几个单词beetles、confectioners、sun和sea有着奇怪的执念。
|
||||
|
||||
### 总结!
|
||||
|
||||
至此,我的结果远不及Karpathy的好,可能有一下几个原因:
|
||||
1. 没有足够多的训练数据。
|
||||
2. 训练了一个小时之后我就没有耐心去查看Colab notebook上的信息。
|
||||
3. Karpathy使用了两层LSTM,包含了更多的参数,而我只使用了一层。
|
||||
4. 完全是另一回事。
|
||||
|
||||
但我得到了一些大致说得过去的结果!还不错!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2020/11/30/implement-char-rnn-in-pytorch/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zhangxiangping](https://github.com/zxp93)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://karpathy.github.io/2015/05/21/rnn-effectiveness/
|
||||
[2]: https://gist.github.com/jvns/b6dda36b2fdcc02b833ed5b0c7a09112
|
||||
[3]: https://www.gutenberg.org/cache/epub/27200/pg27200.txt
|
||||
[4]: https://en.wikipedia.org/wiki/Backpropagation_through_time
|
@ -0,0 +1,114 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to Pretty Print JSON File in Linux Terminal)
|
||||
[#]: via: (https://itsfoss.com/pretty-print-json-linux/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
如何在 Linux 终端上漂亮地打印 JSON 文件
|
||||
======
|
||||
|
||||
[JSON][1] 文件非常棒,因为它们以人类可读的格式存储数据集合。然而,如果 JSON 文件被最小化过,那么阅读 JSON 文件可能会很痛苦。
|
||||
|
||||
以这个为例:
|
||||
|
||||
![Minified JSON is difficult to read][2]
|
||||
|
||||
计算机可以很容易地读取它。即使是人也能读懂,但如果 JSON 文件以合适的格式显示,那么阅读就会简单很多。我的意思是 JSON 文件应该是这样读的:
|
||||
|
||||
![Pretty Printed JSON is easier to read][3]
|
||||
|
||||
你可以使用大多数的文本编辑器和一些插件以合适的格式显示它。然而,如果你在终端中,或者你想在你的 shell 脚本中这么做,事情会有所不同。
|
||||
|
||||
如果你有一个已最小化的文件,让我来告诉你如何在 Linux 终端中漂亮地打印 JSON 文件。
|
||||
|
||||
### 在 Linux 中用 jq 命令漂亮地打印 JSON 文件
|
||||
|
||||
[jq][4] 是一个命令行 JSON 处理器。你可以用它来切分、过滤、映射和转换结构化数据。我在这里不打算详细介绍 jq 命令行工具的使用。
|
||||
|
||||
要使用 jq,你需要先安装它。你可以使用你的[发行版的包管理器][5]来安装它。如果启用了 [universe 仓库][6],你可以使用 apt 命令在 Ubuntu 上安装它:
|
||||
|
||||
```
|
||||
sudo apt install jq
|
||||
```
|
||||
|
||||
安装好后,用下面的方法在显示屏上漂亮地打印 JSON 文件:
|
||||
|
||||
```
|
||||
jq . sample.json
|
||||
```
|
||||
|
||||
![Pretty printed JSON file][7]
|
||||
|
||||
你可能也想用 cat,但我认为 cat 在这里没用。
|
||||
|
||||
```
|
||||
cat sample.json | jq
|
||||
```
|
||||
|
||||
请记住,上述命令不会影响原始 JSON 文件。不会向它写入任何更改。
|
||||
|
||||
你可能已经知道[如何在 Linux 中把命令输出重定向到一个文件][8]。你可能也知道不能重定向到同一个文件,而且 tee 命令也不能保证一直有效。
|
||||
|
||||
如果你想用漂亮的格式修改原来的 JSON 文件,可以把解析后的输出结果用管道传送到一个新的文件中,然后覆盖原来的 JSON 文件。
|
||||
|
||||
```
|
||||
jq . sample.json > pretty.json
|
||||
```
|
||||
|
||||
![Pretty printing JSON file in Linux Terminal][9]
|
||||
|
||||
#### 额外技巧:用 jq 命令对 JSON 文件最小化。
|
||||
|
||||
让我们反过来,对一个格式良好的 JSON 文件进行最小化。要最小化 JSON 文件,你可以使用选项 -c。
|
||||
|
||||
```
|
||||
jq -c < pretty.json
|
||||
```
|
||||
|
||||
![Minified JSON file display][10]
|
||||
|
||||
如果你愿意,你也可以使用 cat 和重定向:
|
||||
|
||||
```
|
||||
cat pretty.json | jq -c
|
||||
```
|
||||
|
||||
### 在 Linux 中使用 Python 来漂亮地打印 JSON 文件
|
||||
|
||||
你更有可能是在系统中安装了 Python。如果是这样的话,你可以用它在终端漂亮地打印 JSON 文件:
|
||||
|
||||
```
|
||||
python3 -m json.tool sample.json
|
||||
```
|
||||
|
||||
![Pretty printing JSON with Python][11]
|
||||
|
||||
我知道还有其他方法可以解析 JSON 文件并以适当的格式打印出来。你可以自己去探索,但这两种方法足以完成漂亮地打印 JSON 文件的工作。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/pretty-print-json-linux/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.json.org
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/12/print-json.png?resize=759%2C253&ssl=1
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-printed-json.png?resize=696%2C538&ssl=1
|
||||
[4]: https://stedolan.github.io/jq/
|
||||
[5]: https://itsfoss.com/package-manager/
|
||||
[6]: https://itsfoss.com/ubuntu-repositories/
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-print-json-linux-terminal.png?resize=750%2C557&ssl=1
|
||||
[8]: https://itsfoss.com/save-command-output-to-file-linux/
|
||||
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-printing-json-linux-terminal.png?resize=750%2C576&ssl=1
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/12/minify-json-file-linux.png?resize=777%2C253&ssl=1
|
||||
[11]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/12/pretty-print-json-with-python.png?resize=777%2C557&ssl=1
|
Loading…
Reference in New Issue
Block a user