deepwalk源码解读2: __main__.py

【论文逐句精读】DeepWalk,随机游走实现图向量嵌入,自然语言处理与图的首次融合 这是一篇划时代的论文,标志着图机器学习向图深度学习的转变,主要贡献在于取代人工图特征标注,转化为无监督图嵌入向量描述。 阅读详情

1. 准备工作


deepwalk源代码链接
https://github.com/sunxiangguo/NRL_deepwalk


__main()__.py 文件是程序的入口,主要包含两段代码,一个是main(),用于定义命令行参数,一个是process(args) 用于解析命令行参数。还有一些代码片段是日志和debug使用的,为了不影响对代码的分析,我们将这两部分代码注释掉。


另一方面,我们如果想要在IDE里(如pycharm)分析源代码,不可能每一次都使用命令行进行,因此这里面使用了一个技巧,即源程序在定义完入口命令行参数后,使用了args = parser.parse_args() 来接送实际使用命令行时的输入,我们这里把这句代码替换为:

args= parser.parse_args("--input ../example_graphs/karate.adjlist "
                        "--output ./output".split())

这样就可以脱离命令行终端,直接在IDE里进行分析。


2. 详细解读

2.0 完整源代码

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import random
from io import open
from argparse import ArgumentParser, FileType, ArgumentDefaultsHelpFormatter
from collections import Counter
from concurrent.futures import ProcessPoolExecutor
import logging

from . import graph
from . import walks as serialized_walks
from gensim.models import Word2Vec
from .skipgram import Skipgram

from six import text_type as unicode
from six import iteritems
from six.moves import range

import psutil
from multiprocessing import cpu_count

p = psutil.Process(os.getpid())
try:
    p.set_cpu_affinity(list(range(cpu_count())))
except AttributeError:
    try:
        p.cpu_affinity(list(range(cpu_count())))
    except AttributeError:
        pass

logger = logging.getLogger(__name__)
LOGFORMAT = "%(asctime).19s %(levelname)s %(filename)s: %(lineno)s %(message)s"


def debug(type_, value, tb):
  if hasattr(sys, 'ps1') or not sys.stderr.isatty():
    sys.__excepthook__(type_, value, tb)
  else:
    import traceback
    import pdb
    traceback.print_exception(type_, value, tb)
    print(u"\n")
    pdb.pm()


def process(args):

  if args.format == "adjlist":
    G = graph.load_adjacencylist(args.input, undirected=args.undirected)
  elif args.format == "edgelist":
    G = graph.load_edgelist(args.input, undirected=args.undirected)
  elif args.format == "mat":
    G = graph.load_matfile(args.input, variable_name=args.matfile_variable_name, undirected=args.undirected)
  else:
    raise Exception("Unknown file format: '%s'.  Valid formats: 'adjlist', 'edgelist', 'mat'" % args.format)

  print("Number of nodes: {}".format(len(G.nodes())))

  num_walks = len(G.nodes()) * args.number_walks

  print("Number of walks: {}".format(num_walks))

  data_size = num_walks * args.walk_length

  print("Data size (walks*length): {}".format(data_size))

  if data_size < args.max_memory_data_size:
    print("Walking...")
    walks = graph.build_deepwalk_corpus(G, num_paths=args.number_walks,
                                        path_length=args.walk_length, alpha=0, rand=random.Random(args.seed))
    print("Training...")
    model = Word2Vec(walks, size=args.representation_size, window=args.window_size, min_count=0, sg=1, hs=1, workers=args.workers)
  else:
    print("Data size {} is larger than limit (max-memory-data-size: {}).  Dumping walks to disk.".format(data_size, args.max_memory_data_size))
    print("Walking...")

    walks_filebase = args.output + ".walks"
    walk_files = serialized_walks.write_walks_to_disk(G, walks_filebase, num_paths=args.number_walks,
                                         path_length=args.walk_length, alpha=0, rand=random.Random(args.seed),
                                         num_workers=args.workers)

    print("Counting vertex frequency...")
    if not args.vertex_freq_degree:
      vertex_counts = serialized_walks.count_textfiles(walk_files, args.workers)
    else:
      # use degree distribution for frequency in tree
      vertex_counts = G.degree(nodes=G.iterkeys())

    print("Training...")
    walks_corpus = serialized_walks.WalksCorpus(walk_files)
    model = Skipgram(sentences=walks_corpus, vocabulary_counts=vertex_counts,
                     size=args.representation_size,
                     window=args.window_size, min_count=0, trim_rule=None, workers=args.workers)

  model.wv.save_word2vec_format(args.output)


def main():
  parser = ArgumentParser("deepwalk",
                          formatter_class=ArgumentDefaultsHelpFormatter,
                          conflict_handler='resolve')

  parser.add_argument("--debug", dest="debug", action='store_true', default=False,
                      help="drop a debugger if an exception is raised.")

  parser.add_argument('--format', default='adjlist',
                      help='File format of input file')

  parser.add_argument('--input', nargs='?', required=True,
                      help='Input graph file')

  parser.add_argument("-l", "--log", dest="log", default="INFO",
                      help="log verbosity level")

  parser.add_argument('--matfile-variable-name', default='network',
                      help='variable name of adjacency matrix inside a .mat file.')

  parser.add_argument('--max-memory-data-size', default=1000000000, type=int,
                      help='Size to start dumping walks to disk, instead of keeping them in memory.')

  parser.add_argument('--number-walks', default=10, type=int,
                      help='Number of random walks to start at each node')

  parser.add_argument('--output', required=True,
                      help='Output representation file')

  parser.add_argument('--representation-size', default=64, type=int,
                      help='Number of latent dimensions to learn for each node.')

  parser.add_argument('--seed', default=0, type=int,
                      help='Seed for random walk generator.')

  parser.add_argument('--undirected', default=True, type=bool,
                      help='Treat graph as undirected.')

  parser.add_argument('--vertex-freq-degree', default=False, action='store_true',
                      help='Use vertex degree to estimate the frequency of nodes '
                           'in the random walks. This option is faster than '
                           'calculating the vocabulary.')

  parser.add_argument('--walk-length', default=40, type=int,
                      help='Length of the random walk started at each node')

  parser.add_argument('--window-size', default=5, type=int,
                      help='Window size of skipgram model.')

  parser.add_argument('--workers', default=1, type=int,
                      help='Number of parallel processes.')


  args = parser.parse_args()
  numeric_level = getattr(logging, args.log.upper(), None)
  logging.basicConfig(format=LOGFORMAT)
  logger.setLevel(numeric_level)

  if args.debug:
   sys.excepthook = debug

  process(args)

if __name__ == "__main__":
  sys.exit(main())

2.1 import

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import random

from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter

from deepwalk import graph
from deepwalk import walks as serialized_walks
from gensim.models import Word2Vec
from deepwalk.skipgram import Skipgram

graph里面有randowalk
walks里也有randowalk
两者的主要区别是前者针对小数据,后这针对大数据,前者采样的路径不会被序列化,后者会被序列化的本地磁盘.但是后者使用的randwalk仍然是graph里定义的方法,实际上是在调用graph.


2.2 main()

def main():
    parser = ArgumentParser("deepwalk",
                            formatter_class=ArgumentDefaultsHelpFormatter,
                            conflict_handler='resolve')
    parser.add_argument("--debug", dest="debug", action='store_true', default=False,
                        help="drop a debugger if an exception is raised.")

    parser.add_argument('--format', default='adjlist',
                        help='File format of input file')
    """
    由于本程序只处理三种类型的输入( 'adjlist','edgelist','mat'),因此这里也可以写成:
    parser.add_argument('--format', default='adjlist',choices=['adjlist','edgelist','mat'],
                        help='File format of input file')
    """

    parser.add_argument('--input', nargs='?', required=True,
                        help='Input graph file')
    """
    这句话的意思是,你的命令行里必须有--input,至于说这个参数后面有没有文件名字无所谓,如果有文件路径,那么input就是
    这个文件;如果没有指定文件路径,那么input=None
    """

    parser.add_argument("-l", "--log", dest="log", default="INFO",
                        help="log verbosity level")

    parser.add_argument('--matfile-variable-name', default='network',
                        help='variable name of adjacency matrix inside a .mat file.')
    """
    这是针对matlab文件.mat设置的,是这个文件内置的邻接矩阵名字。如果我们使用的是karate.adjlist形式的格式,这个地方就可忽略掉
    """

    parser.add_argument('--max-memory-data-size', default=10000, type=int,
                        help='Size to start dumping walks to disk, instead of keeping them in memory.')
    """
    max_memory_data_size在这里不是实际的内存大小,它只是节点使用总次数的计数。
    """




    parser.add_argument('--number-walks', default=10, type=int,
                        help='Number of random walks to start at each node')
    """
    number-walks:相当于你算法里面的$\gamma$
    """

    parser.add_argument('--output', required=True,
                        help='Output representation file')

    parser.add_argument('--representation-size', default=64, type=int,
                        help='Number of latent dimensions to learn for each node.')

    parser.add_argument('--seed', default=0, type=int,
                        help='Seed for random walk generator.')

    parser.add_argument('--undirected', default=True, type=bool,
                        help='Treat graph as undirected.')

    parser.add_argument('--vertex-freq-degree', default=False, action='store_true',
                        help='Use vertex degree to estimate the frequency of nodes '
                             'in the random walks. This option is faster than '
                             'calculating the vocabulary.')


    parser.add_argument('--walk-length', default=40, type=int,
                        help='Length of the random walk started at each node')
    """
    walk_length:相当于你算法里面的$\ell$
    """

    parser.add_argument('--window-size', default=5, type=int,
                        help='Window size of skipgram model.')
    """
      window_size:相当于你算法里面的context size $\omega$
    """

    parser.add_argument('--workers', default=1, type=int,
                        help='Number of parallel processes.')

    # args = parser.parse_args()
    args = parser.parse_args("--input ../example_graphs/karate.adjlist "
                             "--output ./output".split())
    print(args)

    # numeric_level = getattr(logging, args.log.upper(), None)
    # logging.basicConfig(format=LOGFORMAT)
    # logger.setLevel(numeric_level)
    #
    # if args.debug:
    #     sys.excepthook = debug

    process(args)

2.3 process(args)

def process(args):
    """Section1:
      deepwalk的输入可以是三种格式的数据,因此针对这三种格式的数据分别构建图类对象G
      我们这里主要关心的是karae.adjlist和p2p-Gnutella08.edgelist两个文件对应的格式,
      这两个文件都在文件夹example_graphs里面
      对于.mat格式我们不关心,也不使用
    """
    if args.format == "adjlist":
        G = graph.load_adjacencylist(args.input, undirected=args.undirected)
    elif args.format == "edgelist":
        G = graph.load_edgelist(args.input, undirected=args.undirected)
    elif args.format == "mat":
        G = graph.load_matfile(args.input, variable_name=args.matfile_variable_name, undirected=args.undirected)
    else:
        raise Exception("Unknown file format: '%s'.  Valid formats: 'adjlist', 'edgelist', 'mat'" % args.format)



    """Section2:
    下面打印的都是一些基本信息
    """
    print("Number of nodes: {}".format(len(G.nodes())))

    num_walks = len(G.nodes()) * args.number_walks

    print("Number of walks: {}".format(num_walks))

    data_size = num_walks * args.walk_length

    print("Data size (walks*length): {}".format(data_size))



    """Section3:
      这里的data_size不是实际的内存大小,只是节点使用总次数的计数。
      在这个if-else代码段中,更常出现的情况是if,而else里的代码几乎从来不会出现,除非data_size超过了max_memory_data_size
      max_memory_data_size默认的是10亿次。
    """
    if data_size < args.max_memory_data_size:
        print("Walking...")
        walks = graph.build_deepwalk_corpus(G, num_paths=args.number_walks,
                                            path_length=args.walk_length, alpha=0, rand=random.Random(args.seed))
        """
        这里直接调用图对象里的build_deepwalk_corpus,它的主要作用是,对每一个点进行多次随机游走,最后的到全部的walks。
        相当于deepwalk论文里两层for循环randomwalk,
        也相当于node2vec里两层for循环node2vecWalk,
        也相当于你算法里的两层for循环下的adawalk
        num_paths=args.number_walks:是采样的轮数,即每一个起点采样的次数,相当于你论文里的$\gamma$
        path_length=args.walk_length, 
        alpha=0, 指的是以概率1-alpha从当前节点继续走下去(可以回到上一个节点),或者以alpha的概率停止继续走,回到路径的起点重新走。
                 请注意:这里的随机游走路径未必是连续的,有可能是走着走着突然回到起点接着走
                 即便alpha=0,也不能保证以后的路径不会出现起点,因为有可能从起点开始走到第二个点时,这第二个点以1的概率继续走下去,
                 这时候它可能会回到起点。
                 但是如果alpha=1,那么就意味着它不可能继续走下去,只能每次都从起点开始重新走,所以这个时候打印出来的路径序列是一连串的起点。
        rand=random.Random(args.seed)
        """


        print("Training...")

        model = Word2Vec(walks, size=args.representation_size, window=args.window_size, min_count=0, sg=1, hs=1,
                         workers=args.workers)
        """
        这段代码几乎不需要改动,它就是你算法里的SkipGram,你算发里有三个输入:
        random walks---->walks
        context size---->window=args.window_size
        embedding size---->size=args.representation_size
        如果你想对这个模型了解的更多,或者是做更加人性化的定制,需要继续了解from gensim.models import Word2Vec下的源码。
        我们会在下一篇博文中专门解读这个源码
        Word2Vec:

        Initialize the model from an iterable of `sentences`. Each sentence is a
        list of words (unicode strings) that will be used for training.

        Parameters
        ----------
        sentences : iterable of iterables
            The `sentences` iterable can be simply a list of lists of tokens, but for larger corpora,
            consider an iterable that streams the sentences directly from disk/network.
            See :class:`~gensim.models.word2vec.BrownCorpus`, :class:`~gensim.models.word2vec.Text8Corpus`
            or :class:`~gensim.models.word2vec.LineSentence` in :mod:`~gensim.models.word2vec` module for such examples.
            If you don't supply `sentences`, the model is left uninitialized -- use if you plan to initialize it
            in some other way.

        sg : int {1, 0}
            Defines the training algorithm. If 1, skip-gram is employed; otherwise, CBOW is used.
        size : int
            Dimensionality of the feature vectors.
        window : int
            The maximum distance between the current and predicted word within a sentence.
        alpha : float
            The initial learning rate.
        min_alpha : float
            Learning rate will linearly drop to `min_alpha` as training progresses.
        seed : int
            Seed for the random number generator. Initial vectors for each word are seeded with a hash of
            the concatenation of word + `str(seed)`. Note that for a fully deterministically-reproducible run,
            you must also limit the model to a single worker thread (`workers=1`), to eliminate ordering jitter
            from OS thread scheduling. (In Python 3, reproducibility between interpreter launches also requires
            use of the `PYTHONHASHSEED` environment variable to control hash randomization).
        min_count : int
            Ignores all words with total frequency lower than this.
        max_vocab_size : int
            Limits the RAM during vocabulary building; if there are more unique
            words than this, then prune the infrequent ones. Every 10 million word types need about 1GB of RAM.
            Set to `None` for no limit.
        sample : float
            The threshold for configuring which higher-frequency words are randomly downsampled,
            useful range is (0, 1e-5).
        workers : int
            Use these many worker threads to train the model (=faster training with multicore machines).
        hs : int {1,0}
            If 1, hierarchical softmax will be used for model training.
            If set to 0, and `negative` is non-zero, negative sampling will be used.
        negative : int
            If > 0, negative sampling will be used, the int for negative specifies how many "noise words"
            should be drawn (usually between 5-20).
            If set to 0, no negative sampling is used.
        cbow_mean : int {1,0}
            If 0, use the sum of the context word vectors. If 1, use the mean, only applies when cbow is used.
        hashfxn : function
            Hash function to use to randomly initialize weights, for increased training reproducibility.
        iter : int
            Number of iterations (epochs) over the corpus.
        trim_rule : function
            Vocabulary trimming rule, specifies whether certain words should remain in the vocabulary,
            be trimmed away, or handled using the default (discard if word count < min_count).
            Can be None (min_count will be used, look to :func:`~gensim.utils.keep_vocab_item`),
            or a callable that accepts parameters (word, count, min_count) and returns either
            :attr:`gensim.utils.RULE_DISCARD`, :attr:`gensim.utils.RULE_KEEP` or :attr:`gensim.utils.RULE_DEFAULT`.
            Note: The rule, if given, is only used to prune vocabulary during build_vocab() and is not stored as part
            of the model.
        sorted_vocab : int {1,0}
            If 1, sort the vocabulary by descending frequency before assigning word indexes.
        batch_words : int
            Target size (in words) for batches of examples passed to worker threads (and
            thus cython routines).(Larger batches will be passed if individual
            texts are longer than 10000 words, but the standard cython code truncates to that maximum.)
        compute_loss: bool
            If True, computes and stores loss value which can be retrieved using `model.get_latest_training_loss()`.
        callbacks : :obj: `list` of :obj: `~gensim.models.callbacks.CallbackAny2Vec`
            List of callbacks that need to be executed/run at specific stages during training.

        Examples
        --------
        Initialize and train a `Word2Vec` model

        >>> from gensim.models import Word2Vec
        >>> sentences = [["cat", "say", "meow"], ["dog", "say", "woof"]]
        >>>
        >>> model = Word2Vec(sentences, min_count=1)
        >>> say_vector = model['say']  # get vector for word
        """


    else:
        print("Data size {} is larger than limit (max-memory-data-size: {}).  Dumping walks to disk.".format(data_size,
                                                                                                             args.max_memory_data_size))
        print("Walking...")

        """
        在这种情况下,游走路径会被存入到一系列文件output.walks.x中,即如果你在命令行指定了--output file_path
        那么程序结束后会出现两个文件,一个是file_path,一个是file_path.walks.0,file_path.walks.1,...file_path.walks.n。
        file_path存的是各个节点的embedding,
        output.walks.x存的是采样的路径,x表示这个文件是第x个处理器存入的
        x的个数与处理器个数相同
        """
        walks_filebase = args.output + ".walks"
        walk_files = serialized_walks.write_walks_to_disk(G, walks_filebase, num_paths=args.number_walks,
                                                          path_length=args.walk_length, alpha=0,
                                                          rand=random.Random(args.seed),
                                                          num_workers=args.workers)
        """
        在目前的层次上,你只需要知道serialized_walks.write_walks_to_disk本质上也是在调用graph里的randwalk,只不过包装一下
        加入了并行化代码和写到磁盘的程序。
        这个函数具体的细节需要稍后剖析另一个文件walk.py
        函数里各个参数的含义可以参考if语句里面的代码
        """



        # print("Counting vertex frequency...")
        # if not args.vertex_freq_degree:
        #     """Use vertex degree to estimate the frequency of nodes
        #     in the random walks. This option is faster than
        #     calculating the vocabulary."""
        #     vertex_counts = serialized_walks.count_textfiles(walk_files, args.workers)
        # else:
        #     # use degree distribution for frequency in tree
        #     vertex_counts = G.degree(nodes=G.iterkeys())
        #
        # print("Training...")
        # walks_corpus = serialized_walks.WalksCorpus(walk_files)
        # model = Skipgram(sentences=walks_corpus, vocabulary_counts=vertex_counts,
        #                  size=args.representation_size,
        #                  window=args.window_size, min_count=0, trim_rule=None, workers=args.workers)
        """
        上面注释掉的代码是原来的代码,这里没有使用Word2Vec而是使用了自己编写的Skipgram,
        但是Skipgram仅仅是对Word2Vec的输入参数做了一些保装,里面仍然在调用word2vec,
        word2vec本身也可以实现并行化运算,不知道这里为什么要这么做。
        需要说明的是:从现有的情况类看vertex_counts似乎并没什么卵用
        直接向下面这样写就可以:         
        """
        print("Training...")
        walks_corpus = serialized_walks.WalksCorpus(walk_files)
        model = Word2Vec(sentences=walks_corpus,
                         size=args.representation_size,
                         window=args.window_size,
                         min_count=0, sg=1, hs=1,
                         workers=args.workers)


    """Section?:
      训练完成之后,将模型输出
    """
    model.wv.save_word2vec_format(args.output)

2.4 程序入口

if __name__ == "__main__":
    sys.exit(main())

2.5 代码简化

#!usr/bin/env python  
# -*- coding:utf-8 _*-  
""" 
@project:deepwalk-master
@author:xiangguosun 
@contact:sunxiangguodut@qq.com
@website:http://blog.youkuaiyun.com/github_36326955
@file: simple_main.py
@platform: macOS High Sierra 10.13.1 Pycharm pro 2017.1 
@time: 2018/09/13 
"""

import sys
import random

from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from deepwalk import graph
from deepwalk import walks as serialized_walks
from gensim.models import Word2Vec


def process(args):
    if args.format == "adjlist":
        G = graph.load_adjacencylist(args.input, undirected=args.undirected)
    elif args.format == "edgelist":
        G = graph.load_edgelist(args.input, undirected=args.undirected)
    elif args.format == "mat":
        G = graph.load_matfile(args.input, variable_name=args.matfile_variable_name, undirected=args.undirected)
    else:
        raise Exception("Unknown file format: '%s'.  Valid formats: 'adjlist', 'edgelist', 'mat'" % args.format)

    print("Number of nodes: {}".format(len(G.nodes())))

    num_walks = len(G.nodes()) * args.number_walks

    print("Number of walks: {}".format(num_walks))

    data_size = num_walks * args.walk_length

    print("Data size (walks*length): {}".format(data_size))

    print("Walking...")
    walks_filebase = args.output + ".walks"
    walk_files = serialized_walks.write_walks_to_disk(G, walks_filebase, num_paths=args.number_walks,
                                                      path_length=args.walk_length, alpha=0,
                                                      rand=random.Random(args.seed),
                                                      num_workers=args.workers)
    walks = serialized_walks.WalksCorpus(walk_files)

    print("Training...")
    model = Word2Vec(walks, size=args.representation_size, window=args.window_size, min_count=0, sg=1, hs=1,
                     workers=args.workers)

    model.wv.save_word2vec_format(args.output)


def main():
    parser = ArgumentParser("deepwalk",
                            formatter_class=ArgumentDefaultsHelpFormatter,
                            conflict_handler='resolve')
    parser.add_argument("--debug", dest="debug", action='store_true', default=False,
                        help="drop a debugger if an exception is raised.")

    parser.add_argument('--format', default='adjlist', choices=['adjlist', 'edgelist', 'mat'],
                        help='File format of input file')

    parser.add_argument('--input', nargs='?', required=True,
                        help='Input graph file')

    parser.add_argument("-l", "--log", dest="log", default="INFO",
                        help="log verbosity level")

    parser.add_argument('--matfile-variable-name', default='network',
                        help='variable name of adjacency matrix inside a .mat file.')

    parser.add_argument('--number-walks', default=10, type=int,
                        help='Number of random walks to start at each node')

    parser.add_argument('--output', required=True,
                        help='Output representation file')

    parser.add_argument('--representation-size', default=64, type=int,
                        help='Number of latent dimensions to learn for each node.')

    parser.add_argument('--seed', default=0, type=int,
                        help='Seed for random walk generator.')

    parser.add_argument('--undirected', default=True, type=bool,
                        help='Treat graph as undirected.')

    parser.add_argument('--vertex-freq-degree', default=False, action='store_true',
                        help='Use vertex degree to estimate the frequency of nodes '
                             'in the random walks. This option is faster than '
                             'calculating the vocabulary.')

    parser.add_argument('--walk-length', default=40, type=int,
                        help='Length of the random walk started at each node')

    parser.add_argument('--window-size', default=5, type=int,
                        help='Window size of skipgram model.')

    parser.add_argument('--workers', default=1, type=int,
                        help='Number of parallel processes.')

    args = parser.parse_args("--input ../example_graphs/karate.adjlist "
                             "--output ./output".split())
    print(args)

    process(args)


if __name__ == "__main__":
    sys.exit(main())

3. deepwalk文件逻辑

通过对主文件的分析之后,我们整理了整个工程的调用逻辑,如下图:

【AI理论学习】Graph Embedding理论介绍及5种算法演示(DeepWalk) DeepWalk算法思想与 word2vec 类似,**从一个初始节点沿着图中的边随机游走一定的步数,将经过的节点序列视为句子。**那么,从不同的起点开始的不同游走路线就构成了不同的句子。当获取到足够数量的句子(节点访问序列)后,可以使用 skip-gram 模型对每个节点学习其向量表示。 阅读详情

相关推荐

DeepWalk代码实战-维基百科词条图嵌入可视化

DeepWalk代码实战-维基百科词条图嵌入可视化

保持学习 693

论用py制作软件项目基本格式---main.py篇

面向py项目萌新的指导,并非100%准确

BYby_YY_123的博客 2986

TMP112/TMP102温度传感器驱动开发与嵌入式实战

数字温度传感器是嵌入式系统环境感知的核心器件,其通过I²C等标准总线实现高精度、低功耗测温。原理上依赖ΔΣ模数转换与二进制补码数据格式,结合寄存器配置实现模式控制、阈值报警与功耗管理。技术价值体现在±0.5°C级精度、1μA级静态电流及SOT-563超小封装带来的系统集成优势。广泛应用于工业MCU热监控、电池物联网终端、医疗电子温度补偿及汽车ECU板级测温等场景。本文围绕TMP112/TMP102展开,深入解析寄存器协议、硬件接口约束、HAL驱动分层设计、FreeRTOS任务调度及生产级校准方法,覆盖从芯片

weixin_35756690的博客 674

python中main.py是什么意思_关于python:什么是__main__.py?

__main__.py文件是用来做什么的,我应该把什么类型的代码放进去,什么时候应该有一个?通常,通过在命令行中命名.py文件来运行python程序:$ python my_program.py您还可以创建一个包含代码的目录或压缩文件,并包括一个__main__.py。然后您可以在命令行上简单地命名目录或zipfile,它会自动执行__main__.py:$ python my_program_d...

weixin_29941275的博客 1万+

从3dB定向耦合器到双圆极化天线:在HFSS里玩转相位差90°的馈电艺术

本文详细介绍了在HFSS中设计3dB定向耦合器与双圆极化天线的关键技术,重点解析了90°相位差生成原理及馈电网络设计。通过HFSS仿真工具,实现从定向耦合器到完整天线系统的集成,优化阵列天线性能,适用于卫星通信和雷达系统。

weixin_33717117的博客 556

Globus数据下载全攻略:从零配置到批量下载大文件(附常见问题解决)

本文详细介绍了Globus数据下载的全流程,从零配置到批量下载大文件的实用技巧,包括环境准备、高级传输策略、性能优化及常见问题解决方案。Globus作为科研数据的高效传输工具,通过并行流传输和自动校验技术,显著提升大规模数据传输的效率和可靠性。

u9v0w的博客 663

deepwalk&node2vec 代码实战

将节点表示为低维、连续、稠密的向量表示。隐式向量embedding中包含了graph中的社群、连接和结构信息,可用于后续节点分类等下游任务。

weixin_51589123的博客 2760

RV1126 MIPI CSI-2驱动RGB888图像采集的V4L2实战解析

本文详细解析了在RV1126平台上通过MIPI CSI-2接口采集RGB888格式图像的完整V4L2实战流程。核心内容包括设备树(DTS)配置、内核驱动适配、Media Controller链路调试,以及使用v4l2-ctl工具进行图像抓取与验证的方法,旨在帮助开发者打通从硬件连接到稳定采集RGB888图像数据的关键环节。

weixin_29161719的博客 166

deepwalk 代码实战

deepwalk 代码实战 Paper原理参考 class DeepWalk: def __init__(self, graph, walk_length, num_walks, workers=1): self.graph = graph self.w2v_model = None self._embeddings = {} self.walker = RandomWalker( graph, p=1, q

发呆的比目鱼的博客 1128

海豚调度器(dolphinscheduler)再次使用,添加钉钉预警

1,首先我们部署是海豚调度器 1.3.8版本,由于页面只有邮件预警,所以在了解源码的同时,需要添加钉钉预警 2,说明,这一块是同事搞的,不是我搞的,新版本的dolphinscheduler已经有了钉钉模块,只是新版本还没有发布 3,我们现在只是添加简单的钉钉预警,任务成功或者失败会发送邮件+钉钉 4,具体操作 找到最新的源码devhttps://github1s.com/apache/dolphinscheduler/blob/dev/dolphinscheduler-alert/src/ma...

qq_31866793的博客 3084

STM32F103C8T6的PC13-15引脚配置避坑指南:为什么你的IO口不工作?

本文详细解析了STM32F103C8T6的PC13-15引脚作为普通IO口不工作的原因及解决方案。这三个引脚默认关联侵入检测和低速外部时钟等特殊功能,需先禁用TAMPER和LSE,并开启AFIO时钟,才能正确配置为普通GPIO。文章提供了标准外设库和HAL库的配置步骤、常见问题排查方法及硬件设计注意事项。

weixin_29169899的博客 522

动手复现DeepWalk代码并实现可视化分析

【代码】动手复现DeepWalk代码并实现可视化分析。

D_Ddd0701的博客 1583

WPF插件架构-如何动态加载封装好的第三方DLL的界面

插件架构中如何自动加载第三方DLL中的UI界面

lg24k的博客 1882

如何运用deepwalk进行图嵌入,写出python代码

DeepWalk是一种用于学习图嵌入的方法,它可以将图中的节点表示为低维的向量。 要运用DeepWalk进行图嵌入,需要安装Gensim库。 首先,需要准备一个无向图的邻接矩阵作为输入。然后,使用Gensim中的Word2Vec模型,将图的每个节点看作是一个单词,并使用节点的出边作为上下文。 接下来,可以使用Word2Vec模型的训练方法来训练模型。最后,使用Word2Vec模型的wv属性可以获取...

weixin_35750953的博客 639

贴片二极管SOD封装详解:SOD-123/323/523尺寸焊盘设计要点

表面贴装技术中,二极管封装尺寸直接决定PCB布局与焊接可靠性。SOD封装作为小外形二极管的主流形态,其SOD-123、SOD-323、SOD-523三种规格分别对应不同的功耗与占板面积权衡。理解封装尺寸、焊盘设计计算逻辑和钢网开窗原理,是避免立碑、虚焊等工艺缺陷的关键。在可穿戴设备、电源保护等空间受限场景中,合理选择封装不仅能优化散热路径,还能提升量产良率。本文从焊盘计算、工艺要点到选型策略,全面解析SOD封装的工程实践。

weixin_42520780的博客 307

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【推荐算法】deepwalk原理,实战以及工程化

最近aigc很火啊,chatgpt都能帮忙写文章了,博客里面也发了一篇gpt写的机器学习的简单入门文章,感觉很生硬,没有特色,也尝试了别的prompt生成一些个性化的文章,还是太过模板化了,工作周报还行,要来写自己的东西还是不能用它。然后的话,那就开始写自己的东西吧,又是好久没写文字了。

凌陨心 1061

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

python main.py是什么意思_什么是__main__.py?

翻过高山走不出你该__main__.py文件是什么?在创建Python模块时,通常使模块在main作为程序的入口点运行时执行某些功能(通常包含在函数中)。这通常通过放置在大多数Python文件底部的以下常用习惯来完成:if__name__=='__main__':#executeonlyifrunastheentrypointintotheprogram...

weixin_36316102的博客 7637

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

DeepWalk代码解释

代码运行 对给定的图数据集生成节点的embedding: 先对图中的节点进行随机游走 再将随机游走的路径作为Word2Vec的输入,生成节点的embedding 执行代码如下: python __main__.py --input ../example_graphs/karate.adjlist --output ../example_graphs/karate.embeddings pyt...

Firmiana1220的博客 5929

【Graph Net】【专题系列】一、DeepWalk/Node2Vec代码实战

本文主要通过代码实战介绍基础的两种图嵌入方式DeepWalk、Node2Vec

小博客大智慧 1043

MicroPython+ESP32学习笔记(五) 第一个程序 main.py

今天我们没有使用esp8266 而是使用了一个更高级的esp32模块 某宝上有很多的卖家 随便挑一家就是了   【下面是正文】   插上板子 打开uPyCraft 选好串口号 点击connect链接 在左边device里 就能看到 boot.py main.py两个文件 其中main.py就是写我们自己的代码的地方 双击main.py 打开这个文件 在里面 写啊 写 写一个bl...

niupipiniupipi的博客 6583

CS224W课程学习笔记(三):DeepWalk算法原理与说明

时间到了2014年,那是word2vec问世的第二年,Bryan Perozzi[1]创造性地提出了DeepWalk,将词嵌入的方法引入图嵌入,将图嵌入引入了一个新的时代,文章首图就是以该文章的截图,向作者致敬。DeepWalk提出了“随机游走”的思想,这个思想有点类似搜索算法中的DFS,从某一点出发,以深搜的方式获得一个节点序列。这个序列即可以用来描述节点。参照下图:

submarineas的博客 1899

python中的cli模块_python 模块中的 __init__.py __main__.py

python中文件夹想作为一个模块被引用,则在文件夹内必须要包含 __init__.py 文件,即使此文件为空。如果此模块想要运行则必须要包含 __main__.py 文件。接下来说下两个文件起到的作用。拿 robotframework 模块下的文件举例:__init__.py里面一般包含了需要引用的模块1 from robot.rebot importrebot, rebot_cli2 from...

weixin_39622289的博客 453

Word2Vec—Deepwalk—Node2Vec 算法概述_数学表达_伪代码注释

假设节点t是节点u的邻居,那么u同样也是t的邻居,将这种关系映射到特征空间中那就是,节点u对节点t的影响和节点t对节点u的影响是相同的。在计算机实操中,并不是完全随机抽取负样本,一个单词被选作negative sample的概率跟它出现的频次有关,出现频次越高的单词越容易被选作negative words,这也保证了训练的质量。参数p是控制下一个节点是否选择上一节点的概率,所以参数p若设置较大值,则我们在采样序列过程中会以较小概率的采样一个已经访问过的节点,除非下一个节点没有其他邻域节点了。

MIYUWANZI的博客 1449

实际应用场景:API端点设计

假设我们要求:"为用户注册创建API端点" 传统AI响应: ```javascript // 直接实现,可能遗漏重要细节 app.post('/register', async (req, res) => { // 实现代码... }); ``` 遵循思考先行原则的AI响应: "我假设这个端点需要:1) 验证输入格式 2) 检查邮箱是否已存在 3) 密码哈希存储 4) 返回JWT令牌。这些

gitblog_00145的博客 692
上一篇: deepwalk源码解读1: argparse
下一篇: deepwalk源码解读3:python并行编程
相国大人
博客等级 码龄10年 1009粉丝 132原创
评论 15
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值